From 0ff6ca18eddafd6a086ca8a48dd7251edde5c7c5 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 8 Feb 2019 14:35:16 +0800 Subject: [PATCH 0001/2639] Use https for bmclapi --- .../org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java index 03b1f34c22..efe9025e13 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java @@ -59,8 +59,8 @@ public String injectURL(String baseURL) { return baseURL .replace("https://launchermeta.mojang.com", "https://bmclapi2.bangbang93.com") .replace("https://launcher.mojang.com", "https://bmclapi2.bangbang93.com") - .replace("https://libraries.minecraft.net", "http://bmclapi2.bangbang93.com/libraries") - .replaceFirst("https?://files\\.minecraftforge\\.net/maven", "http://bmclapi2.bangbang93.com/maven") + .replace("https://libraries.minecraft.net", "https://bmclapi2.bangbang93.com/libraries") + .replaceFirst("https?://files\\.minecraftforge\\.net/maven", "https://bmclapi2.bangbang93.com/maven") .replace("http://dl.liteloader.com/versions/versions.json", "https://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json") .replace("http://dl.liteloader.com/versions", "https://bmclapi2.bangbang93.com/maven") .replace("https://authlib-injector.yushi.moe", "https://bmclapi2.bangbang93.com/mirrors/authlib-injector"); From 62c38482f6afd19ce1e5daa5ef7df8912867712f Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 8 Feb 2019 14:55:58 +0800 Subject: [PATCH 0002/2639] polish 639bc58e84b68a7b508ed9ba0a701a13b2fac1b4 see https://github.com/huanghongxun/HMCL/commit/639bc58e84b68a7b508ed9ba0a701a13b2fac1b4#r32215378 --- .../main/java/org/jackhuang/hmcl/game/GameVersion.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 965e229d8a..ed5ac4180b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.game; +import static org.jackhuang.hmcl.util.Logging.LOG; + import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -27,7 +29,6 @@ import org.jenkinsci.constant_pool_scanner.ConstantType; import org.jenkinsci.constant_pool_scanner.StringConstant; -import javax.swing.text.html.Option; import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; @@ -35,6 +36,7 @@ import java.nio.file.Path; import java.util.List; import java.util.Optional; +import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -45,8 +47,9 @@ public final class GameVersion { private static Optional getVersionFromJson(Path versionJson) { try { MinecraftVersion version = JsonUtils.fromNonNullJson(FileUtils.readText(versionJson), MinecraftVersion.class); - return Optional.of(version.name); - } catch (IOException | JsonParseException | NullPointerException e) { + return Optional.ofNullable(version.name); + } catch (IOException | JsonParseException e) { + LOG.log(Level.WARNING, "Failed to parse version.json", e); return Optional.empty(); } } From f0c7f54cc64b19f744635eb02e0eb753f375cf92 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 8 Feb 2019 15:54:28 +0800 Subject: [PATCH 0003/2639] Redownload asset index when install new game --- .../java/org/jackhuang/hmcl/ui/versions/Versions.java | 3 +-- .../jackhuang/hmcl/download/DefaultDependencyManager.java | 2 +- .../org/jackhuang/hmcl/download/DefaultGameBuilder.java | 2 +- .../hmcl/download/game/GameAssetDownloadTask.java | 8 +++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index a810a21d24..45c91f1c10 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -81,8 +81,7 @@ public static void updateVersion(Profile profile, String version) { public static void updateGameAssets(Profile profile, String version) { Version resolvedVersion = profile.getRepository().getResolvedVersion(version); - TaskExecutor executor = new GameAssetIndexDownloadTask(profile.getDependency(), resolvedVersion) - .then(new GameAssetDownloadTask(profile.getDependency(), resolvedVersion)) + TaskExecutor executor = new GameAssetDownloadTask(profile.getDependency(), resolvedVersion, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY) .executor(); Controllers.taskDialog(executor, i18n("version.manage.redownload_assets_index")); executor.start(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 481034a2d1..a955527cac 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -74,7 +74,7 @@ public GameBuilder gameBuilder() { @Override public Task checkGameCompletionAsync(Version version) { return new ParallelTask( - new GameAssetDownloadTask(this, version), + new GameAssetDownloadTask(this, version, GameAssetDownloadTask.DOWNLOAD_INDEX_IF_NECESSARY), new GameLibrariesTask(this, version) ); } 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 fac219b472..5ed67f757e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -54,7 +54,7 @@ public Task buildAsync() { version = version.setId(name).setJar(null); variables.set("version", version); Task result = downloadGameAsync(gameVersion, version).then(new ParallelTask( - new GameAssetDownloadTask(dependencyManager, version), + new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY), new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. 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 b064d3172a..9c435ce41e 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 @@ -53,13 +53,13 @@ public final class GameAssetDownloadTask extends Task { * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ - public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version) { + public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version, boolean forceDownloadingIndex) { this.dependencyManager = dependencyManager; this.version = version; this.assetIndexInfo = version.getAssetIndex(); this.assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId()); - if (!assetIndexFile.exists()) + if (!assetIndexFile.exists() || forceDownloadingIndex) dependents.add(new GameAssetIndexDownloadTask(dependencyManager, version)); } @@ -99,5 +99,7 @@ public void execute() throws Exception { updateProgress(++progress, index.getObjects().size()); } } - + + public static final boolean DOWNLOAD_INDEX_FORCIBLY = true; + public static final boolean DOWNLOAD_INDEX_IF_NECESSARY = false; } From 507cade50dcf78b00ad3723b9e444bd2323cae01 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 8 Feb 2019 17:08:23 +0800 Subject: [PATCH 0004/2639] polish authlib-injector --- .../hmcl/auth/authlibinjector/AuthlibInjectorAccount.java | 2 +- .../hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java index 0e96efdf40..4c8d7d8d9a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java @@ -115,7 +115,7 @@ private static Arguments generateArguments(AuthlibInjectorArtifactInfo artifact, return new Arguments().addJVMArguments( "-javaagent:" + artifact.getLocation().toString() + "=" + server.getUrl(), "-Dauthlibinjector.side=client", - "-Dorg.to2mbn.authlibinjector.config.prefetched=" + Base64.getEncoder().encodeToString(prefetchedMeta.getBytes(UTF_8))); + "-Dauthlibinjector.yggdrasil.prefetched=" + Base64.getEncoder().encodeToString(prefetchedMeta.getBytes(UTF_8))); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java index 566b1bc978..cf3c757e73 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java @@ -127,7 +127,7 @@ private Optional getLocalArtifact() { } } - private class AuthlibInjectorVersionInfo { + private static class AuthlibInjectorVersionInfo { @SerializedName("build_number") public int buildNumber; From 426ea607e88d22319d8fddb9eaf684d6b7d2df4b Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 8 Feb 2019 22:05:16 +0800 Subject: [PATCH 0005/2639] HMCLauncher: try bundled JRE --- HMCLauncher/HMCL/HMCL.cpp | Bin 12854 -> 0 bytes HMCLauncher/HMCL/HMCL.h | Bin 80 -> 0 bytes HMCLauncher/HMCL/HMCL.vcxproj | 12 ++- HMCLauncher/HMCL/HMCL.vcxproj.filters | 22 +++++- HMCLauncher/HMCL/Version.cpp | 15 ++++ HMCLauncher/HMCL/Version.h | 20 +++++ HMCLauncher/HMCL/java.cpp | 88 +++++++++++++++++++++ HMCLauncher/HMCL/java.h | 10 +++ HMCLauncher/HMCL/main.cpp | 79 +++++++++++++++++++ HMCLauncher/HMCL/main.h | 3 + HMCLauncher/HMCL/os.cpp | 108 ++++++++++++++++++++++++++ HMCLauncher/HMCL/os.h | 23 ++++++ 12 files changed, 375 insertions(+), 5 deletions(-) delete mode 100644 HMCLauncher/HMCL/HMCL.cpp delete mode 100644 HMCLauncher/HMCL/HMCL.h create mode 100644 HMCLauncher/HMCL/Version.cpp create mode 100644 HMCLauncher/HMCL/Version.h create mode 100644 HMCLauncher/HMCL/java.cpp create mode 100644 HMCLauncher/HMCL/java.h create mode 100644 HMCLauncher/HMCL/main.cpp create mode 100644 HMCLauncher/HMCL/main.h create mode 100644 HMCLauncher/HMCL/os.cpp create mode 100644 HMCLauncher/HMCL/os.h diff --git a/HMCLauncher/HMCL/HMCL.cpp b/HMCLauncher/HMCL/HMCL.cpp deleted file mode 100644 index 94c42fbbbede8c231ba7eb534e0a83256482ff32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12854 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 diff --git a/HMCLauncher/HMCL/HMCL.h b/HMCLauncher/HMCL/HMCL.h deleted file mode 100644 index c4aafa38ed5f51ce4664cbebc89f024a8e8eb731..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmW-YK?;B%00ieO_y^Iuf0C36Dx>iG*6LxGWtjbX;N~H*a;hDbi-m&4%mnsH4jNh9 Q;pG=znN4fBkxg_wevTFn3;+NC diff --git a/HMCLauncher/HMCL/HMCL.vcxproj b/HMCLauncher/HMCL/HMCL.vcxproj index 9b6e9113d0..03e8ac938a 100644 --- a/HMCLauncher/HMCL/HMCL.vcxproj +++ b/HMCLauncher/HMCL/HMCL.vcxproj @@ -23,7 +23,7 @@ {672B1019-E741-4C0D-A986-627E2ACE157B} Win32Proj HMCL - 8.1 + 7.0 @@ -152,19 +152,25 @@ - + + + + - + + + Create Create Create Create + diff --git a/HMCLauncher/HMCL/HMCL.vcxproj.filters b/HMCLauncher/HMCL/HMCL.vcxproj.filters index 04ebb26ddc..e4fb0ec74d 100644 --- a/HMCLauncher/HMCL/HMCL.vcxproj.filters +++ b/HMCLauncher/HMCL/HMCL.vcxproj.filters @@ -24,7 +24,16 @@ 头文件 - + + 头文件 + + + 头文件 + + + 头文件 + + 头文件 @@ -32,7 +41,16 @@ 源文件 - + + 源文件 + + + 源文件 + + + 源文件 + + 源文件 diff --git a/HMCLauncher/HMCL/Version.cpp b/HMCLauncher/HMCL/Version.cpp new file mode 100644 index 0000000000..a8b0279a6a --- /dev/null +++ b/HMCLauncher/HMCL/Version.cpp @@ -0,0 +1,15 @@ +#include "stdafx.h" +#include "Version.h" + +Version::Version(const std::wstring & rawString) +{ + int idx = 0; + ver[0] = ver[1] = ver[2] = ver[3] = 0; + for (auto &i : rawString) + { + if (idx >= 4) break; + if (i == '.') ++idx; + else if (i == '_') ++idx; + else if (isdigit(i)) ver[idx] = ver[idx] * 10 + (i - L'0'); + } +} diff --git a/HMCLauncher/HMCL/Version.h b/HMCLauncher/HMCL/Version.h new file mode 100644 index 0000000000..2e0784d16d --- /dev/null +++ b/HMCLauncher/HMCL/Version.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +class Version +{ +public: + int ver[4]; + + Version(const std::wstring &rawString); + + bool operator<(const Version &other) const + { + for (int i = 0; i < 4; ++i) + if (ver[i] != other.ver[i]) + return ver[i] < other.ver[i]; + return false; + } +}; + diff --git a/HMCLauncher/HMCL/java.cpp b/HMCLauncher/HMCL/java.cpp new file mode 100644 index 0000000000..93e806e665 --- /dev/null +++ b/HMCLauncher/HMCL/java.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#include "java.h" +#include "os.h" + +const Version JAVA_8(L"1.8"), JAVA_11(L"11"); + +const LPCWSTR JDK_OLD = L"SOFTWARE\\JavaSoft\\Java Development Kit"; +const LPCWSTR JRE_OLD = L"SOFTWARE\\JavaSoft\\Java Runtime Environment"; +const LPCWSTR JDK_NEW = L"SOFTWARE\\JavaSoft\\JDK"; +const LPCWSTR JRE_NEW = L"SOFTWARE\\JavaSoft\\JRE"; + +bool oldJavaFound = false, newJavaFound = false; + +bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring & path) +{ + WCHAR javaVer[MAX_KEY_LENGTH]; // buffer for subkey name, special for JavaVersion + DWORD cbName; // size of name string + DWORD cSubKeys = 0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + LSTATUS result; + + HKEY hKey; + if (ERROR_SUCCESS != (result = RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ, &hKey))) + return false; + + RegQueryInfoKey( + hKey, // key handle + NULL, // buffer for class name + NULL, // size of class string + NULL, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + NULL, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + NULL, // security descriptor + NULL); // last write time + + if (!cSubKeys) + return false; + + bool flag = false; + for (DWORD i = 0; i < cSubKeys; ++i) + { + cbName = MAX_KEY_LENGTH; + if (ERROR_SUCCESS != (result = RegEnumKeyEx(hKey, i, javaVer, &cbName, NULL, NULL, NULL, NULL))) + continue; + + HKEY javaKey; + if (ERROR_SUCCESS != RegOpenKeyEx(hKey, javaVer, 0, KEY_READ, &javaKey)) + continue; + + if (ERROR_SUCCESS == MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, path)) + { + if (Version(javaVer) < JAVA_8) + oldJavaFound = true; + else if (!(Version(javaVer) < JAVA_11)) + newJavaFound = true; + else + flag = true; + } + + if (flag) + break; + } + + RegCloseKey(hKey); + + return flag; +} + +bool FindJavaInRegistry(std::wstring & path) +{ + return FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_OLD, path) || + FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_OLD, path) || + FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_NEW, path) || + FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_NEW, path); +} + +bool FindJava(std::wstring & path) +{ + return FindJavaInRegistry(path) || + ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", path); +} diff --git a/HMCLauncher/HMCL/java.h b/HMCLauncher/HMCL/java.h new file mode 100644 index 0000000000..86e96ecd35 --- /dev/null +++ b/HMCLauncher/HMCL/java.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include "Version.h" + +// Find Java installation in system registry +bool FindJavaInRegistry(std::wstring &path); + +// Find Java Installation in registry and environment variable +bool FindJava(std::wstring &path); diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp new file mode 100644 index 0000000000..61fd58e7a2 --- /dev/null +++ b/HMCLauncher/HMCL/main.cpp @@ -0,0 +1,79 @@ +#include "stdafx.h" +#include "main.h" +#include "os.h" +#include "java.h" + +using namespace std; + + +void LaunchJVM(const wstring &javaPath, const wstring &jarPath) +{ + if (MyCreateProcess(L"\"" + javaPath + L"\" -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15 -jar \"" + jarPath + L"\"")) + exit(EXIT_SUCCESS); +} + +int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) +{ + wstring path, exeName; + + // Since Jar file is appended to this executable, we should first get the location of JAR file. + if (ERROR_SUCCESS != MyGetModuleFileName(NULL, exeName)) + return 1; + + + // First try the Java packaged together. + bool is64Bit = false; + GetArch(is64Bit); // if failed to determine architecture of operating system, consider 32-bit. + + if (is64Bit) + { + LaunchJVM(L"jre-x64\\bin\\javaw.exe", exeName); + } + else + { + LaunchJVM(L"jre-x86\\bin\\javaw.exe", exeName); + } + + if (FindJava(path)) + LaunchJVM(path + L"\\bin\\javaw.exe", exeName); + + // Try java in PATH + LaunchJVM(L"javaw", exeName); + + // Or we try to search Java in C:\Program Files. + { + WIN32_FIND_DATA data; + HANDLE hFind = FindFirstFile(L"C:\\Program Files\\Java\\*", &data); // Search all subdirectory + + if (hFind != INVALID_HANDLE_VALUE) { + do { + wstring javaw = wstring(L"C:\\Program Files\\Java\\") + data.cFileName + wstring(L"\\bin\\javaw.exe"); + if (FindFirstFileExists(javaw.c_str(), 0)) { + LaunchJVM(javaw, exeName); + } + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + } + + // Consider C:\Program Files (x86)\Java + { + WIN32_FIND_DATA data; + HANDLE hFind = FindFirstFile(L"C:\\Program Files (x86)\\Java\\*", &data); // Search all subdirectory + + if (hFind != INVALID_HANDLE_VALUE) { + do { + wstring javaw = wstring(L"C:\\Program Files (x86)\\Java\\") + data.cFileName + L"\\bin\\javaw.exe"; + if (FindFirstFileExists(javaw.c_str(), 0)) { + LaunchJVM(javaw, exeName); + } + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + } + + MessageBox(NULL, L"Java installation cannot be found in this computer, please download it from https://java.com \n" + L"未能在这台电脑上找到Java 8~Java 10,请从 https://java.com 下载安装Java", L"Error", MB_ICONERROR | MB_OK); + ShellExecute(0, 0, L"https://java.com/", 0, 0, SW_SHOW); + return 1; +} diff --git a/HMCLauncher/HMCL/main.h b/HMCLauncher/HMCL/main.h new file mode 100644 index 0000000000..e60f2eb7ed --- /dev/null +++ b/HMCLauncher/HMCL/main.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/HMCLauncher/HMCL/os.cpp b/HMCLauncher/HMCL/os.cpp new file mode 100644 index 0000000000..820e53819d --- /dev/null +++ b/HMCLauncher/HMCL/os.cpp @@ -0,0 +1,108 @@ +#include "stdafx.h" +#include "os.h" + +using namespace std; + +LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, wstring &out) +{ + DWORD dwSize = 0; + LSTATUS ret = RegQueryValueEx(hKey, subKey, 0, &dwType, NULL, &dwSize); + if (ret != ERROR_SUCCESS) return ret; + WCHAR *buffer = new WCHAR[dwSize]; + ret = RegQueryValueEx(hKey, subKey, 0, &dwType, (LPBYTE)buffer, &dwSize); + if (ret != ERROR_SUCCESS) return ret; + out = buffer; + delete[] buffer; + return ERROR_SUCCESS; +} + +LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out) +{ + DWORD res, size = MAX_PATH; + out = wstring(); + out.resize(size); + while ((res = GetModuleFileName(hModule, &out[0], size)) == size) + { + out.resize(size += MAX_PATH); + } + if (res == 0) + return GetLastError(); + else + { + out.resize(size - MAX_PATH + res); + return ERROR_SUCCESS; + } +} + +LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring & out) +{ + DWORD res, size = MAX_PATH; + out = wstring(); + out.resize(size); + while ((res = GetEnvironmentVariable(name, &out[0], size)) == size) + { + out.resize(size += MAX_PATH); + } + if (res == 0) + return GetLastError(); + else + { + out.resize(size - MAX_PATH + res); + return ERROR_SUCCESS; + } +} + +bool MyCreateProcess(const std::wstring &command) +{ + wstring writable_command = command; + STARTUPINFO si; + PROCESS_INFORMATION pi; + si.cb = sizeof(si); + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + + return (CreateProcess(NULL, &writable_command[0], NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)); +} + +bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter) +{ + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(lpPath, &fd); + bool bFilter = (false == dwFilter) ? true : fd.dwFileAttributes & dwFilter; + bool ret = ((hFind != INVALID_HANDLE_VALUE) && bFilter) ? true : false; + FindClose(hFind); + return ret; +} + +bool GetArch(bool & is64Bit) +{ +#if _WIN64 + isWindows64bit = true; + return true; +#elif _WIN32 + typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + + BOOL isWow64 = FALSE; + + // IsWow64Process is not available on all supported versions of Windows. + // Use GetModuleHandle to get a handle to the DLL that contains the function + // and GetProcAddress to get a pointer to the function if available. + + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) + GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); + + if (fnIsWow64Process) + { + if (!fnIsWow64Process(GetCurrentProcess(), &isWow64)) + return false; + + is64Bit = isWow64; + return true; + } + else // IsWow64Process is not supported, fail to detect. + return false; + +#else +#error _WIN64 and _WIN32 are both undefined. +#endif +} diff --git a/HMCLauncher/HMCL/os.h b/HMCLauncher/HMCL/os.h new file mode 100644 index 0000000000..406e661b4b --- /dev/null +++ b/HMCLauncher/HMCL/os.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +const int MAX_KEY_LENGTH = 255; +const int MAX_VALUE_NAME = 16383; + +// Query registry value of class root hKey, key path subKey, stores result in parameter out. +LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, std::wstring &out); + +// Get module file name, stores result in parameter out. +LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out); + +// Get environment variable by name, C++ style, stores the value in parameter out. +LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring &out); + +// Create process by invoking CreateProcess, only pass command. +bool MyCreateProcess(const std::wstring &command); + +// Check if file lpPath exists. +bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter); + +bool GetArch(bool &is64Bit); \ No newline at end of file From 8d75b2d413c4f658412f41e11f2f7fa6c6c446c6 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 9 Feb 2019 21:37:26 +0800 Subject: [PATCH 0006/2639] Fix #519 --- HMCL/src/main/resources/assets/css/root.css | 46 ++------------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 1e5b15ad2c..bc1aed23fe 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -536,62 +536,24 @@ * * *******************************************************************************/ -.custom-jfx-button-raised .jfx-rippler { - -jfx-rippler-fill: YELLOW; -} - -.custom-jfx-button-raised { - -fx-padding: 0.7em 0.57em; - -fx-font-size: 14.0px; - -jfx-button-type: RAISED; - -fx-background-color: rgb(102.0, 153.0, 102.0); - -fx-pref-width: 200.0; - -fx-text-fill: WHITE; -} - -.circle-jfx-button-raised .jfx-rippler { - -jfx-rippler-fill: YELLOW; -} - -.circle-jfx-button-raised { - -fx-padding: 0.7em 0.57em; - -fx-font-size: 14.0px; - -jfx-button-type: RAISED; - -fx-background-color: rgb(102.0, 153.0, 102.0); - -fx-pref-width: 200.0; - -fx-text-fill: WHITE; - -jfx-mask-type: CIRCLE; -} - .jfx-button-raised { - -fx-text-fill: white; -fx-background-color: -fx-base-color; - -fx-font-size: 14px; } -.jfx-button-raised .jfx-rippler { - -jfx-rippler-fill: white; -} - -.jfx-button-raised .label { - -fx-text-fill: white; +.jfx-button-raised, .jfx-button-raised * { + -fx-text-fill: -fx-base-text-fill; -fx-font-size: 14px; } .jfx-button-border { - -fx-text-fill: -fx-base-color; -fx-border-color: gray; -fx-border-radius: 5px; -fx-border-width: 0.2px; -fx-padding: 8px; } -.jfx-button-border .jfx-rippler { - -jfx-rippler-fill: -fx-base-check-color; -} - -.jfx-button-border .label { - -fx-text-fill: -fx-base-color; +.jfx-button-border, .jfx-button-border * { + -fx-text-fill: -fx-base-darker-color; } .jfx-button-raised-round { From 0bee306d67f1dcf90c5b6309fba9f6745d222205 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 9 Feb 2019 21:44:14 +0800 Subject: [PATCH 0007/2639] css clean up --- HMCL/src/main/resources/assets/css/root.css | 133 -------------------- 1 file changed, 133 deletions(-) diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index bc1aed23fe..68fcfcf4dc 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -342,7 +342,6 @@ .jfx-tool-bar HBox { -fx-alignment: center; -/* -fx-spacing: 25.0;*/ -fx-padding: 0.0 5.0; } @@ -447,33 +446,6 @@ -fx-fill: -fx-base-check-color; } -.custom-jfx-radio-button { - -fx-font-size: 16.0px; -} - -.custom-jfx-radio-button .radio { - -fx-stroke-width: 2.0px; - -fx-fill: transparent; -} - -.custom-jfx-radio-button-blue { - -fx-text-fill: -fx-base-color; - -jfx-selected-color: -fx-base-color; - -jfx-unselected-color: #212121; -} - -.custom-jfx-radio-button-red { - -fx-text-fill: #f44336; - -jfx-selected-color: #f44336; - -jfx-unselected-color: #b71c1c; -} - -.custom-jfx-radio-button-green { - -fx-text-fill: #4caf50; - -jfx-selected-color: #4caf50; - -jfx-unselected-color: #1b5e20; -} - /******************************************************************************* * * * JFX Slider * @@ -514,18 +486,12 @@ -fx-font-size: 10.0; } -/******************************************************/ - /******************************************************************************* * * * JFX Rippler * * * *******************************************************************************/ -/*.jfx-rippler { - -fx-rippler-fill: -fx-base-color; - -fx-mask-type: RECT; -}*/ .jfx-rippler:hover { -fx-cursor: hand; } @@ -572,20 +538,6 @@ -jfx-checked-color: -fx-base-check-color; } -.custom-jfx-check-box { - -jfx-checked-color: RED; -} - -.custom-jfx-check-box-all-colored { - -jfx-checked-color: -fx-base-color; - -jfx-unchecked-color: -fx-base-color; - -fx-text-fill: -fx-base-color; -} - -.custom-jfx-check-box-text-colored { - -fx-text-fill: rgb(153.0, 0.0, 0.0); -} - /******************************************************************************* * * * JFX Progress Bar * @@ -609,15 +561,6 @@ -fx-background-color: -fx-base-check-color; } -.custom-jfx-progress-bar > .bar { - -fx-background-color: rgb(255.0, 128.0, 0.0); -} - -.custom-jfx-progress-bar-stroke > .bar { - -fx-background-color: -fx-base-color; - -fx-padding: 6; -} - /******************************************************************************* * * * JFX Textfield * @@ -670,47 +613,6 @@ -jfx-expanded: false; } -.custom-jfx-list-view .jfx-list-cell:odd:selected > .jfx-rippler > StackPane, -.custom-jfx-list-view .jfx-list-cell:even:selected > .jfx-rippler > StackPane { - -fx-background-color: rgba(255, 0, 0, 0.2); -} - -.custom-jfx-list-view { - -fx-background-insets: 0.0; - -jfx-cell-horizontal-margin: 0.0; - -jfx-cell-vertical-margin: 5.0; - -jfx-expanded: false; - -fx-max-width: 200.0px; - /* important to hide the list change of height */ - -fx-background-color: TRANSPARENT; -} - -.custom-jfx-list-view .jfx-rippler { - -jfx-rippler-fill: RED; -} - -.custom-jfx-list-view1 { - -jfx-vertical-gap: 10.0; - -fx-pref-width: 150px; - -fx-background-color: transparent; -} - -.custom-jfx-list-view-icon, -.jfx-list-cell:selected .label .custom-jfx-list-view-icon { - -fx-fill: -fx-base-color; - -fx-padding: 0.0 10.0 0.0 5.0; - -fx-cursor: hand; -} - -.custom-jfx-list-view-icon-container { - -fx-pref-width: 40px; -} - -.custom-jfx-list-view .sublist-item { - -fx-border-color: #e0e0e0; - -fx-border-width: 1 0 1 0; -} - .options-list { -fx-background-color: transparent; -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.26), 5, 0.06, -0.5, 1); @@ -760,20 +662,6 @@ -jfx-mask-type: CIRCLE; } -.custom-jfx-list-view .jfx-list-cell .sublist-header > .drop-icon { - -fx-background-color: GRAY; -} - -.custom-jfx-list-view .jfx-list-cell:filled:hover .sublist-header > .drop-icon { - -fx-background-color: BLACK; -} - -/*******************************************************************************/ -/*******************************************************************************/ -/*******************************************************************************/ -/*******************************************************************************/ -/*******************************************************************************/ -/*******************************************************************************/ /******************************************************************************* * * * JFX SUBLIST IMPORTANT * @@ -813,10 +701,6 @@ -fx-padding: 0 0 0 12; } -/*.custom-jfx-list-view .sublist-container { - -fx-padding : 0 0 5 0; -}*/ - /******************************************************************************* * * * JFX Toggle Button * @@ -827,14 +711,6 @@ -jfx-toggle-color: -fx-base-check-color; } -.custom-jfx-toggle-button { - -jfx-toggle-color: #4285F4; -} - -.custom-jfx-toggle-button-red { - -jfx-toggle-color: red; -} - .toggle-label { -fx-font-size: 14.0px; } @@ -1324,12 +1200,3 @@ .fit-width { -fx-pref-width: 100%; } -/* -.jfx-scroll-pane .main-header { - -fx-background-image: url("../bg1.jpg"); -} - -.jfx-scroll-pane .condensed-header { - -fx-background-image: url("../bg4.jpg"); -} -*/ \ No newline at end of file From e8f5088049081094746f21a09f455224b6fb9639 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 10 Feb 2019 10:49:48 +0800 Subject: [PATCH 0008/2639] Support automatic installation of Forge 1.13. --- .../forge/ForgeNewInstallProfile.java | 183 +++++++++++++ .../download/forge/ForgeNewInstallTask.java | 249 ++++++++++++++++++ .../hmcl/download/game/GameLibrariesTask.java | 15 +- .../org/jackhuang/hmcl/game/Artifact.java | 97 +++++++ .../hmcl/game/DefaultGameRepository.java | 16 +- .../org/jackhuang/hmcl/util/StringUtils.java | 8 +- .../util/function/ExceptionalFunction.java | 4 + .../org/jackhuang/hmcl/util/io/FileUtils.java | 16 ++ 8 files changed, 578 insertions(+), 10 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java new file mode 100644 index 0000000000..3cd83c53a1 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java @@ -0,0 +1,183 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.download.forge; + +import org.jackhuang.hmcl.game.Artifact; +import org.jackhuang.hmcl.game.Library; +import org.jackhuang.hmcl.util.Immutable; +import org.jackhuang.hmcl.util.function.ExceptionalFunction; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Immutable +public class ForgeNewInstallProfile { + + private final int spec; + private final String minecraft; + private final String json; + private final List libraries; + private final List processors; + private final Map data; + + public ForgeNewInstallProfile(int spec, String minecraft, String json, List libraries, List processors, Map data) { + this.spec = spec; + this.minecraft = minecraft; + this.json = json; + this.libraries = libraries; + this.processors = processors; + this.data = data; + } + + /** + * Specification for install_profile.json. + */ + public int getSpec() { + return spec; + } + + /** + * Vanilla game version that this installer supports. + */ + public String getMinecraft() { + return minecraft; + } + + /** + * Version json to be installed. + * @return path of the version json relative to the installer JAR file. + */ + public String getJson() { + return json; + } + + /** + * Libraries that processors depend on. + * @return the required dependencies. + */ + public List getLibraries() { + return libraries == null ? Collections.emptyList() : libraries; + } + + /** + * Tasks to be executed to setup modded environment. + */ + public List getProcessors() { + if (processors == null) return Collections.emptyList(); + return processors.stream().filter(p -> p.isSide("client")).collect(Collectors.toList()); + } + + /** + * Data for processors. + */ + public Map getData() { + if (data == null) + return new HashMap<>(); + + return data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getClient())); + } + + public static class Processor { + private final List sides; + private final Artifact jar; + private final List classpath; + private final List args; + private final Map outputs; + + public Processor(List sides, Artifact jar, List classpath, List args, Map outputs) { + this.sides = sides; + this.jar = jar; + this.classpath = classpath; + this.args = args; + this.outputs = outputs; + } + + /** + * Check which side this processor should be run on. We only support client install currently. + * @param side can be one of "client", "server", "extract". + * @return true if the processor can run on the side. + */ + public boolean isSide(String side) { + return sides == null || sides.contains(side); + } + + /** + * The executable jar of this processor task. Will be executed in installation process. + * @return the artifact path of executable jar. + */ + public Artifact getJar() { + return jar; + } + + /** + * The dependencies of this processor task. + * @return the artifact path of dependencies. + */ + public List getClasspath() { + return classpath == null ? Collections.emptyList() : classpath; + } + + /** + * Arguments to pass to the processor jar. + * Each item can be in one of the following formats: + * [artifact]: An artifact path, used for locating files. + * {entry}: Get corresponding value of the entry in {@link ForgeNewInstallProfile#getData()} + * {MINECRAFT_JAR}: path of the Minecraft jar. + * {SIDE}: values other than "client" will be ignored. + * @return arguments to pass to the processor jar. + * @see ForgeNewInstallTask#parseLiteral(String, Map, ExceptionalFunction) + */ + public List getArgs() { + return args == null ? Collections.emptyList() : args; + } + + /** + * File-checksum pairs, used for verifying the output file is correct. + * Arguments to pass to the processor jar. + * Keys can be in one of [artifact] or {entry}. Should be file path. + * Values can be in one of {entry} or 'literal'. Should be SHA-1 checksum. + * @return files output from this processor. + * @see ForgeNewInstallTask#parseLiteral(String, Map, ExceptionalFunction) + */ + public Map getOutputs() { + return outputs == null ? Collections.emptyMap() : outputs; + } + } + + public static class Datum { + private final String client; + + public Datum(String client) { + this.client = client; + } + + /** + * Can be in the following formats: + * [value]: An artifact path. + * 'value': A string literal. + * value: A file in the installer package, to be extracted to a temp folder, and then have the absolute path in replacements. + * @return Value to use for the client install + */ + public String getClient() { + return client; + } + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java new file mode 100644 index 0000000000..2e9f51f923 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -0,0 +1,249 @@ +package org.jackhuang.hmcl.download.forge; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.game.GameLibrariesTask; +import org.jackhuang.hmcl.game.*; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.function.ExceptionalFunction; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.ChecksumMismatchException; +import org.jackhuang.hmcl.util.io.CompressingUtils; +import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.platform.CommandBuilder; +import org.jackhuang.hmcl.util.platform.JavaVersion; +import org.jackhuang.hmcl.util.platform.OperatingSystem; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.stream.Collectors; + +import static org.jackhuang.hmcl.util.DigestUtils.digest; +import static org.jackhuang.hmcl.util.Hex.encodeHex; +import static org.jackhuang.hmcl.util.Logging.LOG; + +public class ForgeNewInstallTask extends TaskResult { + + private final DefaultDependencyManager dependencyManager; + private final DefaultGameRepository gameRepository; + private final Version version; + private final Path installer; + private final List dependents = new LinkedList<>(); + private final List dependencies = new LinkedList<>(); + + private ForgeNewInstallProfile profile; + private Version forgeVersion; + + public ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { + this.dependencyManager = dependencyManager; + this.gameRepository = dependencyManager.getGameRepository(); + this.version = version; + this.installer = installer; + } + + private String parseLiteral(String literal, Map var, ExceptionalFunction plainConverter) throws E { + if (StringUtils.isSurrounded(literal, "{", "}")) + return var.get(StringUtils.removeSurrounding(literal, "{", "}")); + else if (StringUtils.isSurrounded(literal, "'", "'")) + return StringUtils.removeSurrounding(literal, "'"); + else if (StringUtils.isSurrounded(literal, "[", "]")) + return gameRepository.getArtifactFile(version, new Artifact(StringUtils.removeSurrounding(literal, "[", "]"))).toString(); + else + return plainConverter.apply(literal); + } + + @Override + public Collection getDependents() { + return dependents; + } + + @Override + public List getDependencies() { + return dependencies; + } + + @Override + public String getId() { + return "version"; + } + + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void preExecute() throws Exception { + try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { + profile = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath("install_profile.json")), ForgeNewInstallProfile.class); + forgeVersion = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath(profile.getJson())), Version.class); + + for (Library library : profile.getLibraries()) { + Path file = fs.getPath("maven").resolve(library.getPath()); + if (Files.exists(file)) { + Path dest = gameRepository.getLibraryFile(version, library).toPath(); + FileUtils.copyFile(file, dest); + } + } + } + + dependents.add(new GameLibrariesTask(dependencyManager, version, profile.getLibraries())); + } + + @Override + public void execute() throws Exception { + Path temp = Files.createTempDirectory("forge_installer"); + int finished = 0; + try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { + List processors = profile.getProcessors(); + Map data = profile.getData(); + + updateProgress(0, processors.size()); + + for (Map.Entry entry : data.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + + data.put(key, parseLiteral(value, + Collections.emptyMap(), + str -> { + Path dest = temp.resolve(str); + FileUtils.copyFile(fs.getPath(str), dest); + return dest.toString(); + })); + } + + data.put("SIDE", "client"); + data.put("MINECRAFT_JAR", gameRepository.getVersionJar(version).getAbsolutePath()); + + for (ForgeNewInstallProfile.Processor processor : processors) { + Map outputs = new HashMap<>(); + boolean miss = false; + + for (Map.Entry entry : processor.getOutputs().entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + + key = parseLiteral(key, data, ExceptionalFunction.identity()); + value = parseLiteral(value, data, ExceptionalFunction.identity()); + + if (key == null || value == null) { + throw new Exception("Invalid forge installation configuration"); + } + + outputs.put(key, value); + + Path artifact = Paths.get(key); + if (Files.exists(artifact)) { + String code; + try (InputStream stream = Files.newInputStream(artifact)) { + code = encodeHex(digest("SHA-1", stream)); + } + + if (!Objects.equals(code, value)) { + Files.delete(artifact); + LOG.info("Found existing file is not valid: " + artifact); + + miss = true; + } + } else { + miss = true; + } + } + + if (!processor.getOutputs().isEmpty() && !miss) { + continue; + } + + Path jar = gameRepository.getArtifactFile(version, processor.getJar()); + if (!Files.isRegularFile(jar)) + throw new FileNotFoundException("Game processor file not found, should be downloaded in preprocess"); + + String mainClass; + try (JarFile jarFile = new JarFile(jar.toFile())) { + mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); + } + + if (StringUtils.isBlank(mainClass)) + throw new Exception("Game processor jar does not have main class " + jar); + + List command = new ArrayList<>(); + command.add(JavaVersion.fromCurrentEnvironment().getBinary().toString()); + command.add("-cp"); + + List classpath = new ArrayList<>(processor.getClasspath().size() + 1); + for (Artifact artifact : processor.getClasspath()) { + Path file = gameRepository.getArtifactFile(version, artifact); + if (!Files.isRegularFile(file)) + throw new Exception("Game processor dependency missing"); + classpath.add(file.toString()); + } + classpath.add(jar.toString()); + command.add(String.join(OperatingSystem.PATH_SEPARATOR, classpath)); + + command.add(mainClass); + + List args = processor.getArgs().stream().map(arg -> { + String parsed = parseLiteral(arg, data, ExceptionalFunction.identity()); + if (parsed == null) + throw new IllegalStateException("Invalid forge installation configuration"); + return parsed; + }).collect(Collectors.toList()); + + command.addAll(args); + + LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString()); + Process process = new ProcessBuilder(command).start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + for (String line; (line = reader.readLine()) != null;) { + System.out.println(line); + } + } + int exitCode = process.waitFor(); + if (exitCode != 0) + throw new IllegalStateException("Game processor exited abnormally"); + + for (Map.Entry entry : outputs.entrySet()) { + Path artifact = Paths.get(entry.getKey()); + if (!Files.isRegularFile(artifact)) + throw new FileNotFoundException("File missing: " + artifact); + + String code; + try (InputStream stream = Files.newInputStream(artifact)) { + code = encodeHex(digest("SHA-1", stream)); + } + + if (!Objects.equals(code, entry.getValue())) { + Files.delete(artifact); + throw new ChecksumMismatchException("SHA-1", entry.getValue(), code); + } + } + + updateProgress(++finished, processors.size()); + } + } + + // resolve the version + SimpleVersionProvider provider = new SimpleVersionProvider(); + provider.addVersion(version); + + setResult(forgeVersion + .setInheritsFrom(version.getId()) + .resolve(provider).setJar(null) + .setId(version.getId()).setLogging(Collections.emptyMap())); + + dependencies.add(dependencyManager.checkLibraryCompletionAsync(forgeVersion)); + + FileUtils.deleteDirectory(temp.toFile()); + } +} 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 58649803bb..35519cec7b 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 @@ -36,6 +36,7 @@ public final class GameLibrariesTask extends Task { private final AbstractDependencyManager dependencyManager; private final Version version; + private final List libraries; private final List dependencies = new LinkedList<>(); /** @@ -45,8 +46,20 @@ public final class GameLibrariesTask extends Task { * @param version the resolved version */ public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version) { + this(dependencyManager, version, version.getLibraries()); + } + + /** + * Constructor. + * + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} + * @param version the resolved version + */ + public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version, List libraries) { this.dependencyManager = dependencyManager; this.version = version; + this.libraries = libraries; + setSignificance(TaskSignificance.MODERATE); } @@ -57,7 +70,7 @@ public List getDependencies() { @Override public void execute() { - version.getLibraries().stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { + libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { File file = dependencyManager.getGameRepository().getLibraryFile(version, library); if (!file.exists()) dependencies.add(new LibraryDownloadTask(dependencyManager, file, library)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java new file mode 100644 index 0000000000..34419f2b24 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java @@ -0,0 +1,97 @@ +package org.jackhuang.hmcl.game; + +import com.google.gson.*; +import com.google.gson.annotations.JsonAdapter; +import org.jackhuang.hmcl.util.Immutable; + +import java.lang.reflect.Type; +import java.nio.file.Path; + +@Immutable +@JsonAdapter(Artifact.Serializer.class) +public final class Artifact { + + private final String group; + private final String name; + private final String version; + private final String classifier; + private final String extension; + + private final String descriptor; + private final String fileName; + private final String path; + + public Artifact(String descriptor) { + this.descriptor = descriptor; + + String[] arr = descriptor.split(":", 4); + if (arr.length != 3 && arr.length != 4) + throw new IllegalArgumentException("Artifact name is malformed"); + + String ext = null; + int last = arr.length - 1; + String[] splitted = arr[last].split("@"); + if (splitted.length == 2) { + arr[last] = splitted[0]; + ext = splitted[1]; + } else if (splitted.length > 2) { + throw new IllegalArgumentException("Artifact name is malformed"); + } + + this.group = arr[0].replace("\\", "/"); + this.name = arr[1]; + this.version = arr[2]; + this.classifier = arr.length >= 4 ? arr[3] : null; + this.extension = ext == null ? "jar" : ext; + + String fileName = this.name + "-" + this.version; + if (classifier != null) fileName += "-" + this.classifier; + this.fileName = fileName + "." + this.extension; + this.path = String.format("%s/%s/%s/%s", this.group.replace(".", "/"), this.name, this.version, this.fileName); + } + + public String getGroup() { + return group; + } + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + public String getClassifier() { + return classifier; + } + + public String getExtension() { + return extension; + } + + public String getFileName() { + return fileName; + } + + public Path getPath(Path root) { + return root.resolve(path); + } + + @Override + public String toString() { + return descriptor; + } + + public static class Serializer implements JsonDeserializer, JsonSerializer { + @Override + public JsonElement serialize(Artifact src, Type typeOfSrc, JsonSerializationContext context) { + return src == null ? JsonNull.INSTANCE : new JsonPrimitive(src.toString()); + } + + @Override + public Artifact deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return json.isJsonPrimitive() ? new Artifact(json.getAsJsonPrimitive().getAsString()) : null; + } + } +} 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 42069173db..c42edb4b96 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -20,19 +20,19 @@ import com.google.gson.JsonParseException; import org.jackhuang.hmcl.event.*; import org.jackhuang.hmcl.mod.ModManager; -import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import static org.jackhuang.hmcl.util.Logging.LOG; - import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.*; import java.util.logging.Level; import java.util.stream.Stream; +import static org.jackhuang.hmcl.util.Logging.LOG; + /** * An implementation of classic Minecraft game repository. * @@ -82,6 +82,10 @@ public File getLibraryFile(Version version, Library lib) { return new File(getBaseDirectory(), "libraries/" + lib.getPath()); } + public Path getArtifactFile(Version version, Artifact artifact) { + return artifact.getPath(getBaseDirectory().toPath().resolve("libraries")); + } + @Override public File getRunDirectory(String id) { return getBaseDirectory(); @@ -265,10 +269,8 @@ public void refreshVersions() { if (EventBus.EVENT_BUS.fireEvent(new RefreshingVersionsEvent(this)) == Event.Result.DENY) return; - Schedulers.newThread().schedule(() -> { - refreshVersionsImpl(); - EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); - }); + refreshVersionsImpl(); + EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java index aaf7483812..354950a0f7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.util; +import org.jackhuang.hmcl.util.platform.OperatingSystem; + import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.Collection; @@ -24,8 +26,6 @@ import java.util.List; import java.util.StringTokenizer; -import org.jackhuang.hmcl.util.platform.OperatingSystem; - /** * * @author huangyuhui @@ -128,6 +128,10 @@ public static String substringAfter(String str, String delimiter, String missing return index == -1 ? missingDelimiterValue : str.substring(index + delimiter.length()); } + public static boolean isSurrounded(String str, String prefix, String suffix) { + return str.startsWith(prefix) && str.endsWith(suffix); + } + public static String removeSurrounding(String str, String delimiter) { return removeSurrounding(str, delimiter, delimiter); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalFunction.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalFunction.java index 082e9f8239..59a1aa1078 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalFunction.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalFunction.java @@ -23,4 +23,8 @@ */ public interface ExceptionalFunction { R apply(T t) throws E; + + static ExceptionalFunction identity() { + return t -> t; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java index 2b6b2856d8..52fe65a8f4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java @@ -275,6 +275,22 @@ public static void copyFile(File srcFile, File destFile) Files.copy(srcFile.toPath(), destFile.toPath(), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); } + public static void copyFile(Path srcFile, Path destFile) + throws IOException { + Objects.requireNonNull(srcFile, "Source must not be null"); + Objects.requireNonNull(destFile, "Destination must not be null"); + if (!Files.exists(srcFile)) + throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); + if (Files.isDirectory(srcFile)) + throw new IOException("Source '" + srcFile + "' exists but is a directory"); + Path parentFile = destFile.getParent(); + Files.createDirectories(parentFile); + if (Files.exists(destFile) && !Files.isWritable(destFile)) + throw new IOException("Destination '" + destFile + "' exists but is read-only"); + + Files.copy(srcFile, destFile, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + } + public static void moveFile(File srcFile, File destFile) throws IOException { copyFile(srcFile, destFile); srcFile.delete(); From 9a6f07d7c968364ed8ada0774f02d110f0093605 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 10 Feb 2019 10:51:04 +0800 Subject: [PATCH 0009/2639] make DefaultGameRepositoy.readVersionJson nonnull. --- .../org/jackhuang/hmcl/game/HMCLGameRepository.java | 7 ------- .../jackhuang/hmcl/game/DefaultGameRepository.java | 6 +++--- .../main/java/org/jackhuang/hmcl/game/Library.java | 4 ++-- .../hmcl/mod/MultiMCModpackInstallTask.java | 3 +-- .../src/main/java/org/jackhuang/hmcl/util/Lang.java | 13 +++---------- .../hmcl/util/versioning/VersionNumber.java | 1 + HMCLauncher/HMCL/main.cpp | 2 +- 7 files changed, 11 insertions(+), 25 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 4c0146bcf7..9177da0d37 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -80,13 +80,6 @@ protected void refreshVersionsImpl() { } } - @Override - public void refreshVersions() { - EventBus.EVENT_BUS.fireEvent(new RefreshingVersionsEvent(this)); - refreshVersionsImpl(); - EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); - } - public void changeDirectory(File newDirectory) { setBaseDirectory(newDirectory); refreshVersionsAsync().start(); 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 c42edb4b96..f20eda3cfd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -117,7 +117,7 @@ public Version readVersionJson(String id) throws IOException, JsonParseException } public Version readVersionJson(File file) throws IOException, JsonParseException { - return JsonUtils.GSON.fromJson(FileUtils.readText(file), Version.class); + return JsonUtils.fromNonNullJson(FileUtils.readText(file), Version.class); } @Override @@ -221,7 +221,7 @@ protected void refreshVersionsImpl() { Version version; try { - version = Objects.requireNonNull(readVersionJson(json)); + version = readVersionJson(json); } catch (Exception e) { LOG.log(Level.WARNING, "Malformed version json " + id, e); // JsonSyntaxException or IOException or NullPointerException(!!) @@ -229,7 +229,7 @@ protected void refreshVersionsImpl() { return Stream.empty(); try { - version = Objects.requireNonNull(readVersionJson(json)); + version = readVersionJson(json); } catch (Exception e2) { LOG.log(Level.SEVERE, "User corrected version json is still malformed", e2); return Stream.empty(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Library.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Library.java index 49360eca61..73e8a9de3e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Library.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Library.java @@ -45,13 +45,13 @@ public class Library implements Comparable { private final String classifier; private final String url; private final LibrariesDownloadInfo downloads; - private final LibraryDownloadInfo download; + private transient final LibraryDownloadInfo download; private final ExtractRules extract; private final Map natives; private final List rules; private final List checksums; - private final String path; + private transient final String path; public Library(String groupId, String artifactId, String version) { this(groupId, artifactId, version, null, null, null); 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 4dd991b8b2..b9c6b06eac 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -40,7 +40,6 @@ import java.nio.file.Path; import java.util.LinkedList; import java.util.List; -import java.util.Objects; import java.util.Optional; /** @@ -133,7 +132,7 @@ public List getDependents() { @Override public void execute() throws Exception { - Version version = Objects.requireNonNull(repository.readVersionJson(name)); + Version version = repository.readVersionJson(name); try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(zipFile.toPath())) { Path root = Files.list(fs.getPath("/")).filter(Files::isDirectory).findAny() diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index 6d5ee2b82b..195d7cf184 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -17,14 +17,15 @@ */ package org.jackhuang.hmcl.util; +import org.jackhuang.hmcl.util.function.ExceptionalRunnable; +import org.jackhuang.hmcl.util.function.ExceptionalSupplier; + import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; -import org.jackhuang.hmcl.util.function.ExceptionalSupplier; /** * @@ -203,14 +204,6 @@ public static Integer toIntOrNull(Object string) { } } - public static Double toDoubleOrNull(Object string) { - try { - return Double.parseDouble(string.toString()); - } catch (NumberFormatException e) { - return null; - } - } - /** * Find the first non-null reference in given list. * @param t nullable references list. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java index 228586411b..55d0bc7b4b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java @@ -25,6 +25,7 @@ /** * Copied from org.apache.maven.artifact.versioning.ComparableVersion * Apache License 2.0 + * @see Specification */ public class VersionNumber implements Comparable { diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp index 61fd58e7a2..905b311414 100644 --- a/HMCLauncher/HMCL/main.cpp +++ b/HMCLauncher/HMCL/main.cpp @@ -20,7 +20,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd if (ERROR_SUCCESS != MyGetModuleFileName(NULL, exeName)) return 1; - + // TODO: check whether the bundled JRE is valid. // First try the Java packaged together. bool is64Bit = false; GetArch(is64Bit); // if failed to determine architecture of operating system, consider 32-bit. From c889d7cb3f8293ab62a4a5ea030b5517c1b9db76 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 11 Feb 2019 19:36:19 +0800 Subject: [PATCH 0010/2639] Download missing game jar when launching --- .../hmcl/download/DefaultDependencyManager.java | 11 +++++++---- .../hmcl/download/game/GameDownloadTask.java | 12 ++++++++---- .../src/main/java/org/jackhuang/hmcl/task/Task.java | 4 ---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index a955527cac..7be09a437e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -19,10 +19,7 @@ import org.jackhuang.hmcl.download.forge.ForgeInstallTask; import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion; -import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; -import org.jackhuang.hmcl.download.game.GameLibrariesTask; -import org.jackhuang.hmcl.download.game.LibrariesUniqueTask; -import org.jackhuang.hmcl.download.game.VersionJsonSaveTask; +import org.jackhuang.hmcl.download.game.*; import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask; import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; @@ -74,6 +71,12 @@ public GameBuilder gameBuilder() { @Override public Task checkGameCompletionAsync(Version version) { return new ParallelTask( + Task.ofThen(var -> { + if (!repository.getVersionJar(version).exists()) + return new GameDownloadTask(this, null, version); + else + return null; + }), new GameAssetDownloadTask(this, version, GameAssetDownloadTask.DOWNLOAD_INDEX_IF_NECESSARY), new GameLibrariesTask(this, version) ); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index d463bbb539..f0d4288f1f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -55,14 +55,18 @@ public List getDependencies() { @Override public void execute() { File jar = dependencyManager.getGameRepository().getVersionJar(version); - - dependencies.add(new FileDownloadTask( + + FileDownloadTask task = new FileDownloadTask( NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())), jar, IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1())) .setCaching(true) - .setCacheRepository(dependencyManager.getCacheRepository()) - .setCandidate(dependencyManager.getCacheRepository().getCommonDirectory().resolve("jars").resolve(gameVersion + ".jar"))); + .setCacheRepository(dependencyManager.getCacheRepository()); + + if (gameVersion != null) + task.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory().resolve("jars").resolve(gameVersion + ".jar")); + + dependencies.add(task); } } 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 3ea2d7062d..3938dac5e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -339,10 +339,6 @@ public final Task finalized(Scheduler }); } - public static Task empty() { - return of(ExceptionalConsumer.empty()); - } - public static Task of(String name, ExceptionalRunnable runnable) { return of(name, ExceptionalConsumer.fromRunnable(runnable)); } From 5095640ba2a541337ba6e6cd0595557c641f579e Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 11 Feb 2019 19:47:17 +0800 Subject: [PATCH 0011/2639] Report memory usage when OutOfMemoryError occurred. --- .../src/main/java/org/jackhuang/hmcl/util/CrashReporter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 aad0ae4d6a..f5f99e31f7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -103,7 +103,10 @@ public void uncaughtException(Thread t, Throwable e) { "-- 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"; + " Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n" + + " JVM Max Memory: " + Runtime.getRuntime().maxMemory() + "\n" + + " JVM Total Memory: " + Runtime.getRuntime().totalMemory() + "\n" + + " JVM Free Memory: " + Runtime.getRuntime().freeMemory() + "\n"; LOG.log(Level.SEVERE, text); From 9ced29aa93b855adc1ce472b02a0d270f28f6cdb Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 11 Feb 2019 19:53:55 +0800 Subject: [PATCH 0012/2639] Display furnace image as default for modded 1.13 game --- .../main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java | 2 ++ .../src/main/java/org/jackhuang/hmcl/download/MaintainTask.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 9177da0d37..563aba480a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -161,6 +161,8 @@ public Image getVersionIconImage(String id) { return new Image("file:" + iconFile.getAbsolutePath()); else if ("net.minecraft.launchwrapper.Launch".equals(version.getMainClass())) return new Image("/assets/img/furnace.png"); + else if ("cpw.mods.modlauncher.Launcher".equals(version.getMainClass())) + return new Image("/assets/img/furnace.png"); else return new Image("/assets/img/grass.png"); } 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 156938ff38..9199986659 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -44,7 +44,7 @@ public static Version maintain(Version version) { return maintainGameWithLaunchWrapper(version); } else { // Vanilla Minecraft does not need maintain - // Forge 1.13.2 support not implemented. + // Forge 1.13 support not implemented, not compatible with OptiFine currently. return version; } } From 12b47e7d51299e080e44ab66444c4510f4d08553 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 12 Feb 2019 21:30:45 +0800 Subject: [PATCH 0013/2639] Better prompt of LibraryDownloadException --- .../hmcl/ui/download/ModpackInstallWizardProvider.java | 3 +++ .../hmcl/ui/download/VanillaInstallWizardProvider.java | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index 09d9f7331a..a06c758133 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; +import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.CurseCompletionException; import org.jackhuang.hmcl.mod.MismatchedModpackTypeException; @@ -111,6 +112,8 @@ public void onFail(Map settings, Exception exception, Runnable n } else { Controllers.dialog(i18n("modpack.type.curse.tolerable_error"), i18n("install.success"), MessageBox.INFORMATION_MESSAGE, next); } + } else if (exception instanceof LibraryDownloadException) { + Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); } else if (exception instanceof DownloadException) { Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); } else { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 58227a22a1..b0105819d1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -21,6 +21,7 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Schedulers; @@ -73,7 +74,9 @@ public Object finish(Map settings) { settings.put("failure_callback", new FailureCallback() { @Override public void onFail(Map settings, Exception exception, Runnable next) { - if (exception instanceof DownloadException) { + if (exception instanceof LibraryDownloadException) { + Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); + } else if (exception instanceof DownloadException) { Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); } else { Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); From b62f9494ae868ee39768d75a696f054550e3a247 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 12 Feb 2019 21:39:01 +0800 Subject: [PATCH 0014/2639] Have a placeholder in the bottom of LIstPage --- .../org/jackhuang/hmcl/ui/ListPageSkin.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java index 1e8cc6897c..887afa40cc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java @@ -19,12 +19,13 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXScrollPane; - import javafx.beans.binding.Bindings; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.ScrollPane; import javafx.scene.control.SkinBase; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.setting.Theme; @@ -36,6 +37,7 @@ public ListPageSkin(ListPage skinnable) { super(skinnable); SpinnerPane spinnerPane = new SpinnerPane(); + Pane placeholder = new Pane(); StackPane contentPane = new StackPane(); { @@ -48,9 +50,12 @@ public ListPageSkin(ListPage skinnable) { list.setSpacing(10); list.setPadding(new Insets(10)); + VBox content = new VBox(); + content.getChildren().setAll(list, placeholder); + Bindings.bindContent(list.getChildren(), skinnable.itemsProperty()); - scrollPane.setContent(list); + scrollPane.setContent(content); JFXScrollPane.smoothScrolling(scrollPane); } @@ -86,7 +91,13 @@ public ListPageSkin(ListPage skinnable) { }); } - contentPane.getChildren().setAll(scrollPane, vBox); + // Keep a blank space to prevent buttons from blocking up mod items. + BorderPane group = new BorderPane(); + group.setPickOnBounds(false); + group.setBottom(vBox); + placeholder.minHeightProperty().bind(vBox.heightProperty()); + + contentPane.getChildren().setAll(scrollPane, group); } spinnerPane.loadingProperty().bind(skinnable.loadingProperty()); From 4759e4957c897fd7fd6d691bd5fbb1e22e65f838 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 13 Feb 2019 17:46:11 +0800 Subject: [PATCH 0015/2639] refactor --- .../hmcl/ui/versions/VersionSettingsPage.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index a16ca63d45..5ec170322c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -108,15 +108,15 @@ private void initialize() { FXUtils.smoothScrolling(scroll); - Task.of(variables -> variables.set("list", JavaVersion.getJavas())) - .subscribe(Schedulers.javafx(), variables -> { - javaItem.loadChildren( - (variables.>get("list")).stream() - .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) - .collect(Collectors.toList())); - javaItemsLoaded = true; - initializeSelectedJava(); - }); + Task.ofResult(JavaVersion::getJavas).thenResult(Schedulers.javafx(), list -> { + javaItem.loadChildren(list.stream() + .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", + javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) + .collect(Collectors.toList())); + javaItemsLoaded = true; + initializeSelectedJava(); + return null; + }).start(); javaItem.setSelectedData(null); javaItem.setFallbackData(JavaVersion.fromCurrentEnvironment()); From 6edfd112a26641560f52438f77bfcc708f93626d Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 13 Feb 2019 17:51:01 +0800 Subject: [PATCH 0016/2639] Replace "close" icon to "delete" icon on ModItem --- HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java index 0a6eb22512..d44210d987 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java @@ -52,7 +52,7 @@ public ModItem(ModInfo info, Consumer deleteCallback) { btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this)); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); - btnRemove.setGraphic(SVG.close(Theme.blackFillBinding(), 15, 15)); + btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), 15, 15)); setRight(btnRemove); setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); From 758216245f17a4066ce3b267fbdecd03f368828c Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Wed, 13 Feb 2019 20:05:01 +0800 Subject: [PATCH 0017/2639] Add missing license headers --- .../download/forge/ForgeNewInstallTask.java | 17 +++++++++++++++++ .../java/org/jackhuang/hmcl/game/Artifact.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index 2e9f51f923..8dc7f8a9f8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -1,3 +1,20 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DefaultDependencyManager; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java index 34419f2b24..3fe42e943a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Artifact.java @@ -1,3 +1,20 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ package org.jackhuang.hmcl.game; import com.google.gson.*; From 394873864fbf9d512ef288590b92772cbfa35f05 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Wed, 13 Feb 2019 20:09:51 +0800 Subject: [PATCH 0018/2639] Fix #526 --- .../java/org/jackhuang/hmcl/game/TexturesLoader.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index f1d967a400..028c73ec6d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -180,12 +180,9 @@ public static BufferedImage toAvatar(BufferedImage skin, int size) { faceOffset, faceOffset, size - faceOffset, size - faceOffset, 8 * scale, 8 * scale, 16 * scale, 16 * scale, null); - - if (skin.getWidth() == skin.getHeight()) { - g.drawImage(skin, - 0, 0, size, size, - 40 * scale, 8 * scale, 48 * scale, 16 * scale, null); - } + g.drawImage(skin, + 0, 0, size, size, + 40 * scale, 8 * scale, 48 * scale, 16 * scale, null); g.dispose(); return avatar; From eab4463c2dde963354dcb0c7d57f7da33aceb36d Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 14 Feb 2019 15:34:52 +0800 Subject: [PATCH 0019/2639] HMCLauncher: verify if JVM version is between 8 and 10 --- .../src/main/resources/assets/HMCLauncher.exe | Bin 94208 -> 95744 bytes HMCLauncher/HMCL/HMCL.APS | Bin 50652 -> 8024 bytes HMCLauncher/HMCL/HMCL.rc | Bin 6602 -> 6686 bytes HMCLauncher/HMCL/HMCL.vcxproj | 4 +++ HMCLauncher/HMCL/HMCL.vcxproj.filters | 3 ++ HMCLauncher/HMCL/Version.cpp | 4 ++- HMCLauncher/HMCL/Version.h | 20 +++++++++++ HMCLauncher/HMCL/java.cpp | 2 +- HMCLauncher/HMCL/lang.h | 4 +++ HMCLauncher/HMCL/main.cpp | 25 +++++++++---- HMCLauncher/HMCL/os.cpp | 33 ++++++++++++++++++ HMCLauncher/HMCL/os.h | 5 ++- 12 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 HMCLauncher/HMCL/lang.h diff --git a/HMCL/src/main/resources/assets/HMCLauncher.exe b/HMCL/src/main/resources/assets/HMCLauncher.exe index a4b610ff429999922b057227d27fe8479e464947..9a6ece8e21e0571c97e31322f01faab333dbffc6 100644 GIT binary patch delta 37179 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 z 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 R1Yo$*-j&Bkzqu#C^B+KHCcpl6As!$l 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 YR_17#pU-j4o$|Ac#UIeAcZ$XT1<`bFK>z>% literal 50652 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 HMCL 7.0 + HMCLauncher @@ -94,6 +95,7 @@ Windows true + version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) @@ -129,6 +131,7 @@ true true true + version.lib;%(AdditionalDependencies) @@ -153,6 +156,7 @@ + diff --git a/HMCLauncher/HMCL/HMCL.vcxproj.filters b/HMCLauncher/HMCL/HMCL.vcxproj.filters index e4fb0ec74d..06f818873a 100644 --- a/HMCLauncher/HMCL/HMCL.vcxproj.filters +++ b/HMCLauncher/HMCL/HMCL.vcxproj.filters @@ -36,6 +36,9 @@ 头文件 + + 头文件 + diff --git a/HMCLauncher/HMCL/Version.cpp b/HMCLauncher/HMCL/Version.cpp index a8b0279a6a..9113dc7efd 100644 --- a/HMCLauncher/HMCL/Version.cpp +++ b/HMCLauncher/HMCL/Version.cpp @@ -1,7 +1,9 @@ #include "stdafx.h" #include "Version.h" -Version::Version(const std::wstring & rawString) +using namespace std; + +Version::Version(const wstring & rawString) { int idx = 0; ver[0] = ver[1] = ver[2] = ver[3] = 0; diff --git a/HMCLauncher/HMCL/Version.h b/HMCLauncher/HMCL/Version.h index 2e0784d16d..630b67da2e 100644 --- a/HMCLauncher/HMCL/Version.h +++ b/HMCLauncher/HMCL/Version.h @@ -9,6 +9,18 @@ class Version Version(const std::wstring &rawString); + template + Version(std::initializer_list ver_list) + { + int i = 0; + for (const auto &data : ver_list) + { + if (i >= 4) + break; + ver[i++] = data; + } + } + bool operator<(const Version &other) const { for (int i = 0; i < 4; ++i) @@ -16,5 +28,13 @@ class Version return ver[i] < other.ver[i]; return false; } + + bool operator<=(const Version &other) const + { + for (int i = 0; i < 4; ++i) + if (ver[i] != other.ver[i]) + return ver[i] < other.ver[i]; + return true; + } }; diff --git a/HMCLauncher/HMCL/java.cpp b/HMCLauncher/HMCL/java.cpp index 93e806e665..f4f9579d54 100644 --- a/HMCLauncher/HMCL/java.cpp +++ b/HMCLauncher/HMCL/java.cpp @@ -58,7 +58,7 @@ bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring & path) { if (Version(javaVer) < JAVA_8) oldJavaFound = true; - else if (!(Version(javaVer) < JAVA_11)) + else if (JAVA_11 <= Version(javaVer)) newJavaFound = true; else flag = true; diff --git a/HMCLauncher/HMCL/lang.h b/HMCLauncher/HMCL/lang.h new file mode 100644 index 0000000000..b17749023d --- /dev/null +++ b/HMCLauncher/HMCL/lang.h @@ -0,0 +1,4 @@ +#pragma once + +#define ERROR_PROMPT L"Java installation cannot be found in this computer, please download it from https://java.com \n" \ +L"δ̨ҵJava 8~Java 10 https://java.com ذװJava" \ No newline at end of file diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp index 905b311414..80717d8c8e 100644 --- a/HMCLauncher/HMCL/main.cpp +++ b/HMCLauncher/HMCL/main.cpp @@ -2,16 +2,30 @@ #include "main.h" #include "os.h" #include "java.h" +#include "lang.h" using namespace std; +Version J8(TEXT("8")), J11(TEXT("11")); -void LaunchJVM(const wstring &javaPath, const wstring &jarPath) +void RawLaunchJVM(const wstring &javaPath, const wstring &jarPath) { if (MyCreateProcess(L"\"" + javaPath + L"\" -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15 -jar \"" + jarPath + L"\"")) exit(EXIT_SUCCESS); } +void LaunchJVM(const wstring &javaPath, const wstring &jarPath) +{ + Version javaVersion(L""); + if (!MyGetFileVersionInfo(javaPath, javaVersion)) + return; + + if (J8 <= javaVersion && javaVersion < J11) + { + RawLaunchJVM(javaPath, jarPath); + } +} + int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { wstring path, exeName; @@ -37,9 +51,6 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd if (FindJava(path)) LaunchJVM(path + L"\\bin\\javaw.exe", exeName); - // Try java in PATH - LaunchJVM(L"javaw", exeName); - // Or we try to search Java in C:\Program Files. { WIN32_FIND_DATA data; @@ -72,8 +83,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd } } - MessageBox(NULL, L"Java installation cannot be found in this computer, please download it from https://java.com \n" - L"未能在这台电脑上找到Java 8~Java 10,请从 https://java.com 下载安装Java", L"Error", MB_ICONERROR | MB_OK); + // Try java in PATH + RawLaunchJVM(L"javaw", exeName); + + MessageBox(NULL, ERROR_PROMPT, L"Error", MB_ICONERROR | MB_OK); ShellExecute(0, 0, L"https://java.com/", 0, 0, SW_SHOW); return 1; } diff --git a/HMCLauncher/HMCL/os.cpp b/HMCLauncher/HMCL/os.cpp index 820e53819d..b86d2108ad 100644 --- a/HMCLauncher/HMCL/os.cpp +++ b/HMCLauncher/HMCL/os.cpp @@ -106,3 +106,36 @@ bool GetArch(bool & is64Bit) #error _WIN64 and _WIN32 are both undefined. #endif } + +bool MyGetFileVersionInfo(const std::wstring & filePath, Version &version) +{ + DWORD verHandle = 0; + UINT size = 0; + LPBYTE lpBuffer = NULL; + VS_FIXEDFILEINFO *pFileInfo; + DWORD dwSize = GetFileVersionInfoSize(filePath.c_str(), NULL); + + if (!dwSize) + return false; + + LPBYTE data = new BYTE[dwSize]; + if (!GetFileVersionInfo(filePath.c_str(), 0, dwSize, data)) + { + delete[] data; + return false; + } + + if (!VerQueryValue(data, TEXT("\\"), (LPVOID*)&pFileInfo, &size)) + { + delete[] data; + return false; + } + + version = Version{ + (pFileInfo->dwFileVersionMS >> 16) & 0xFFFF, + (pFileInfo->dwFileVersionMS >> 0) & 0xFFFF, + (pFileInfo->dwFileVersionLS >> 16) & 0xFFFF, + (pFileInfo->dwFileVersionLS >> 0) & 0xFFFF + }; + return true; +} diff --git a/HMCLauncher/HMCL/os.h b/HMCLauncher/HMCL/os.h index 406e661b4b..e3207899d1 100644 --- a/HMCLauncher/HMCL/os.h +++ b/HMCLauncher/HMCL/os.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "Version.h" const int MAX_KEY_LENGTH = 255; const int MAX_VALUE_NAME = 16383; @@ -20,4 +21,6 @@ bool MyCreateProcess(const std::wstring &command); // Check if file lpPath exists. bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter); -bool GetArch(bool &is64Bit); \ No newline at end of file +bool GetArch(bool &is64Bit); + +bool MyGetFileVersionInfo(const std::wstring &filePath, Version &version); \ No newline at end of file From b3721e29c627a83e4fd32114bfa6ebb3a77b146e Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 14 Feb 2019 16:20:14 +0800 Subject: [PATCH 0020/2639] Update copyright statement --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index c1c0f8228f..f403a75dda 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -18,7 +18,7 @@ # Contributors: dxNeil about.copyright=Copyright -about.copyright.statement=Copyright (c) 2018 huangyuhui. +about.copyright.statement=Copyright (c) 2019 huangyuhui. about.author=Author about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=Thanks to diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4a9c4cf586..0ea29d5f81 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -17,7 +17,7 @@ # about.copyright=版權 -about.copyright.statement=Copyright (c) 2018 huangyuhui. +about.copyright.statement=Copyright (c) 2019 huangyuhui. about.author=作者 about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=鳴謝 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 f6f78acd2b..67c611e1e3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -17,7 +17,7 @@ # about.copyright=版权 -about.copyright.statement=Copyright (c) 2018 huangyuhui. +about.copyright.statement=Copyright (c) 2019 huangyuhui. about.author=作者 about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=鸣谢 From c2d609cdb4ef5ee00b28f827ad910920eceeec81 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 15 Feb 2019 19:39:43 +0800 Subject: [PATCH 0021/2639] Use TableView in ModListPage to allow multiple selection --- .../org/jackhuang/hmcl/ui/ListPageSkin.java | 1 + .../main/java/org/jackhuang/hmcl/ui/SVG.java | 4 + .../construct/JFXCheckBoxTreeTableCell.java | 133 +++++++++++++ .../hmcl/ui/versions/GameListSkin.java | 14 +- .../jackhuang/hmcl/ui/versions/ModItem.java | 73 ------- .../hmcl/ui/versions/ModListPage.java | 105 ++++++---- .../hmcl/ui/versions/ModListPageSkin.java | 187 ++++++++++++++++++ HMCL/src/main/resources/assets/css/root.css | 14 +- .../assets/fxml/download/modpack.fxml | 2 +- .../resources/assets/lang/I18N.properties | 4 + .../resources/assets/lang/I18N_zh.properties | 3 + .../assets/lang/I18N_zh_CN.properties | 3 + .../org/jackhuang/hmcl/mod/ModManager.java | 1 - 13 files changed, 423 insertions(+), 121 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java index 887afa40cc..ae084d9f9b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java @@ -37,6 +37,7 @@ public ListPageSkin(ListPage skinnable) { super(skinnable); SpinnerPane spinnerPane = new SpinnerPane(); + spinnerPane.getStyleClass().add("large-spinner-pane"); Pane placeholder = new Pane(); StackPane contentPane = new StackPane(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 3f18c7678e..fdd64a1756 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -162,4 +162,8 @@ public static Node home(ObjectBinding fill, double width, doubl public static Node viewList(ObjectBinding fill, double width, double height) { return createSVGPath("M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z", fill, width, height); } + + public static Node check(ObjectBinding fill, double width, double height) { + return createSVGPath("M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z", fill, width, height); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java new file mode 100644 index 0000000000..69d415bb19 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java @@ -0,0 +1,133 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.ui.construct; + +import com.jfoenix.controls.JFXCheckBox; +import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Pos; +import javafx.scene.control.CheckBox; +import javafx.scene.control.TreeTableCell; +import javafx.util.Callback; +import javafx.util.StringConverter; + +public class JFXCheckBoxTreeTableCell extends TreeTableCell { + + private final CheckBox checkBox; + private boolean showLabel; + private ObservableValue booleanProperty; + + public JFXCheckBoxTreeTableCell() { + this(null, null); + } + + public JFXCheckBoxTreeTableCell( + final Callback> getSelectedProperty) { + this(getSelectedProperty, null); + } + + public JFXCheckBoxTreeTableCell( + final Callback> getSelectedProperty, + final StringConverter converter) { + this.getStyleClass().add("check-box-tree-table-cell"); + this.checkBox = new JFXCheckBox(); + setGraphic(null); + setSelectedStateCallback(getSelectedProperty); + setConverter(converter); + } + + private ObjectProperty> converter = + new SimpleObjectProperty>(this, "converter") { + protected void invalidated() { + updateShowLabel(); + } + }; + + public final ObjectProperty> converterProperty() { + return converter; + } + public final void setConverter(StringConverter value) { + converterProperty().set(value); + } + public final StringConverter getConverter() { + return converterProperty().get(); + } + + private ObjectProperty>> + selectedStateCallback = + new SimpleObjectProperty>>( + this, "selectedStateCallback"); + + public final ObjectProperty>> selectedStateCallbackProperty() { + return selectedStateCallback; + } + + public final void setSelectedStateCallback(Callback> value) { + selectedStateCallbackProperty().set(value); + } + + public final Callback> getSelectedStateCallback() { + return selectedStateCallbackProperty().get(); + } + + @SuppressWarnings("unchecked") + @Override public void updateItem(T item, boolean empty) { + super.updateItem(item, empty); + + if (empty) { + setText(null); + setGraphic(null); + } else { + StringConverter c = getConverter(); + + if (showLabel) { + setText(c.toString(item)); + } + setGraphic(checkBox); + + if (booleanProperty instanceof BooleanProperty) { + checkBox.selectedProperty().unbindBidirectional((BooleanProperty)booleanProperty); + } + ObservableValue obsValue = getSelectedProperty(); + if (obsValue instanceof BooleanProperty) { + booleanProperty = (ObservableValue) obsValue; + checkBox.selectedProperty().bindBidirectional((BooleanProperty)booleanProperty); + } + + checkBox.disableProperty().bind(Bindings.not( + getTreeTableView().editableProperty().and( + getTableColumn().editableProperty()).and( + editableProperty()) + )); + } + } + + private void updateShowLabel() { + this.showLabel = converter != null; + this.checkBox.setAlignment(showLabel ? Pos.CENTER_LEFT : Pos.CENTER); + } + + private ObservableValue getSelectedProperty() { + return getSelectedStateCallback() != null ? + getSelectedStateCallback().call(getIndex()) : + getTableColumn().getCellObservableValue(getIndex()); + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java index 4e3dda0ccd..c011b27745 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java @@ -19,7 +19,6 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXScrollPane; -import com.jfoenix.controls.JFXSpinner; import com.jfoenix.effects.JFXDepthManager; import javafx.beans.binding.Bindings; import javafx.geometry.Insets; @@ -31,8 +30,8 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.setting.Theme; -import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.util.i18n.I18n; public class GameListSkin extends SkinBase { @@ -91,10 +90,9 @@ public GameListSkin(GameList skinnable) { } { - StackPane center = new StackPane(); - - JFXSpinner spinner = new JFXSpinner(); - spinner.getStyleClass().setAll("first-spinner"); + SpinnerPane center = new SpinnerPane(); + center.loadingProperty().bind(skinnable.loadingProperty()); + center.getStyleClass().add("large-spinner-pane"); ScrollPane scrollPane = new ScrollPane(); scrollPane.setFitToWidth(true); @@ -109,9 +107,7 @@ public GameListSkin(GameList skinnable) { scrollPane.setContent(gameList); JFXScrollPane.smoothScrolling(scrollPane); - FXUtils.onChangeAndOperate(skinnable.loadingProperty(), - loading -> center.getChildren().setAll(loading ? spinner : scrollPane)); - + center.setContent(scrollPane); root.setCenter(center); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java deleted file mode 100644 index d44210d987..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.ui.versions; - -import com.jfoenix.concurrency.JFXUtilities; -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXCheckBox; -import com.jfoenix.effects.JFXDepthManager; -import javafx.geometry.Pos; -import javafx.scene.layout.BorderPane; -import org.jackhuang.hmcl.mod.ModInfo; -import org.jackhuang.hmcl.setting.Theme; -import org.jackhuang.hmcl.ui.FXUtils; -import org.jackhuang.hmcl.ui.SVG; -import org.jackhuang.hmcl.ui.construct.TwoLineListItem; -import org.jackhuang.hmcl.util.StringUtils; - -import java.util.function.Consumer; - -import static org.jackhuang.hmcl.util.i18n.I18n.i18n; - -public final class ModItem extends BorderPane { - - public ModItem(ModInfo info, Consumer deleteCallback) { - JFXCheckBox chkEnabled = new JFXCheckBox(); - BorderPane.setAlignment(chkEnabled, Pos.CENTER); - setLeft(chkEnabled); - - TwoLineListItem modItem = new TwoLineListItem(); - BorderPane.setAlignment(modItem, Pos.CENTER); - setCenter(modItem); - - JFXButton btnRemove = new JFXButton(); - JFXUtilities.runInFX(() -> { - FXUtils.installFastTooltip(btnRemove, i18n("mods.remove")); - }); - btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this)); - btnRemove.getStyleClass().add("toggle-icon4"); - BorderPane.setAlignment(btnRemove, Pos.CENTER); - btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), 15, 15)); - setRight(btnRemove); - - setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); - JFXDepthManager.setDepth(this, 1); - modItem.setTitle(info.getFileName()); - StringBuilder message = new StringBuilder(info.getName()); - if (StringUtils.isNotBlank(info.getVersion())) - message.append(", ").append(i18n("archive.version")).append(": ").append(info.getVersion()); - if (StringUtils.isNotBlank(info.getGameVersion())) - message.append(", ").append(i18n("archive.game_version")).append(": ").append(info.getGameVersion()); - if (StringUtils.isNotBlank(info.getAuthors())) - message.append(", ").append(i18n("archive.author")).append(": ").append(info.getAuthors()); - modItem.setSubtitle(message.toString()); - 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/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index f6c20f8c19..9775eba389 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -19,6 +19,15 @@ import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXTabPane; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.control.Control; +import javafx.scene.control.Skin; +import javafx.scene.control.TreeItem; import javafx.stage.FileChooser; import org.jackhuang.hmcl.mod.ModInfo; import org.jackhuang.hmcl.mod.ModManager; @@ -37,16 +46,18 @@ import java.util.LinkedList; import java.util.List; import java.util.logging.Level; +import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -public final class ModListPage extends ListPage { +public final class ModListPage extends Control { + private final ListProperty items = new SimpleListProperty<>(this, "items", FXCollections.observableArrayList()); + private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading", false); private JFXTabPane parentTab; private ModManager modManager; public ModListPage() { - setRefreshable(true); FXUtils.applyDragListener(this, it -> Arrays.asList("jar", "zip", "litemod").contains(FileUtils.getExtension(it)), mods -> { mods.forEach(it -> { @@ -61,6 +72,10 @@ public ModListPage() { } @Override + protected Skin createDefaultSkin() { + return new ModListPageSkin(this); + } + public void refresh() { loadMods(modManager); } @@ -71,50 +86,22 @@ public void loadVersion(Profile profile, String id) { public void loadMods(ModManager modManager) { this.modManager = modManager; - Task.of(variables -> { + Task.ofResult("list", variables -> { synchronized (ModListPage.this) { JFXUtilities.runInFX(() -> loadingProperty().set(true)); - modManager.refreshMods(); - - // Surprisingly, if there are a great number of mods, this processing will cause a long UI pause, - // constructing UI elements. - // We must do this asynchronously. - LinkedList list = new LinkedList<>(); - for (ModInfo modInfo : modManager.getMods()) { - ModItem item = new ModItem(modInfo, i -> { - try { - modManager.removeMods(modInfo); - } catch (IOException ignore) { - // Fail to remove mods if the game is running or the mod is absent. - } - loadMods(modManager); - }); - modInfo.activeProperty().addListener((a, b, newValue) -> { - if (newValue) - item.getStyleClass().remove("disabled"); - else - item.getStyleClass().add("disabled"); - }); - if (!modInfo.isActive()) - item.getStyleClass().add("disabled"); - - list.add(item); - } - - variables.set("list", list); + return new LinkedList<>(modManager.getMods()); } - }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { + }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { if (newValue != null && newValue.getUserData() == ModListPage.this) - itemsProperty().setAll(variables.>get("list")); + itemsProperty().setAll(list.stream().map(ModListPageSkin.ModInfoObject::new).collect(Collectors.toList())); }); }).start(); } - @Override public void add() { FileChooser chooser = new FileChooser(); chooser.setTitle(i18n("mods.choose_mod")); @@ -151,4 +138,54 @@ public void add() { public void setParentTab(JFXTabPane parentTab) { this.parentTab = parentTab; } + + public void removeSelectedMods(ObservableList> selectedItems) { + try { + modManager.removeMods(selectedItems.stream() + .map(TreeItem::getValue) + .map(ModListPageSkin.ModInfoObject::getModInfo) + .toArray(ModInfo[]::new)); + loadMods(modManager); + } catch (IOException ignore) { + // Fail to remove mods if the game is running or the mod is absent. + } + } + + public void enableSelectedMods(ObservableList> selectedItems) { + selectedItems.stream() + .map(TreeItem::getValue) + .map(ModListPageSkin.ModInfoObject::getModInfo) + .forEach(info -> info.setActive(true)); + } + + public void disableSelectedMods(ObservableList> selectedItems) { + selectedItems.stream() + .map(TreeItem::getValue) + .map(ModListPageSkin.ModInfoObject::getModInfo) + .forEach(info -> info.setActive(false)); + } + + public ObservableList getItems() { + return items.get(); + } + + public void setItems(ObservableList items) { + this.items.set(items); + } + + public ListProperty itemsProperty() { + return items; + } + + public boolean isLoading() { + return loading.get(); + } + + public void setLoading(boolean loading) { + this.loading.set(loading); + } + + public BooleanProperty loadingProperty() { + return loading; + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java new file mode 100644 index 0000000000..224d526733 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -0,0 +1,187 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.ui.versions; + +import com.jfoenix.controls.*; +import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject; +import com.jfoenix.effects.JFXDepthManager; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.util.Callback; +import org.jackhuang.hmcl.mod.ModInfo; +import org.jackhuang.hmcl.setting.Theme; +import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.construct.JFXCheckBoxTreeTableCell; +import org.jackhuang.hmcl.ui.construct.SpinnerPane; + +import java.util.function.Function; + +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + +public class ModListPageSkin extends SkinBase { + + private static Node wrap(Node node) { + StackPane stackPane = new StackPane(); + stackPane.setPadding(new Insets(0, 5, 0, 2)); + stackPane.getChildren().setAll(node); + return stackPane; + } + + public ModListPageSkin(ModListPage skinnable) { + super(skinnable); + + BorderPane root = new BorderPane(); + JFXTreeTableView tableView = new JFXTreeTableView<>(); + + { + HBox toolbar = new HBox(); + toolbar.getStyleClass().setAll("jfx-tool-bar-second"); + JFXDepthManager.setDepth(toolbar, 1); + toolbar.setPickOnBounds(false); + + JFXButton btnRefresh = new JFXButton(); + btnRefresh.getStyleClass().add("jfx-tool-bar-button"); + btnRefresh.textFillProperty().bind(Theme.foregroundFillBinding()); + btnRefresh.setGraphic(wrap(SVG.refresh(Theme.foregroundFillBinding(), -1, -1))); + btnRefresh.setText(i18n("button.refresh")); + btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); + toolbar.getChildren().add(btnRefresh); + + JFXButton btnAddMod = new JFXButton(); + btnAddMod.getStyleClass().add("jfx-tool-bar-button"); + btnAddMod.textFillProperty().bind(Theme.foregroundFillBinding()); + btnAddMod.setGraphic(wrap(SVG.plus(Theme.foregroundFillBinding(), -1, -1))); + btnAddMod.setText(i18n("mods.add")); + btnAddMod.setOnMouseClicked(e -> skinnable.add()); + toolbar.getChildren().add(btnAddMod); + + JFXButton btnRemove = new JFXButton(); + btnRemove.getStyleClass().add("jfx-tool-bar-button"); + btnRemove.textFillProperty().bind(Theme.foregroundFillBinding()); + btnRemove.setGraphic(wrap(SVG.delete(Theme.foregroundFillBinding(), -1, -1))); + btnRemove.setText(i18n("mods.remove")); + btnRemove.setOnMouseClicked(e -> skinnable.removeSelectedMods(tableView.getSelectionModel().getSelectedItems())); + toolbar.getChildren().add(btnRemove); + + JFXButton btnEnable = new JFXButton(); + btnEnable.getStyleClass().add("jfx-tool-bar-button"); + btnEnable.textFillProperty().bind(Theme.foregroundFillBinding()); + btnEnable.setGraphic(wrap(SVG.check(Theme.foregroundFillBinding(), -1, -1))); + btnEnable.setText(i18n("mods.enable")); + btnEnable.setOnMouseClicked(e -> skinnable.enableSelectedMods(tableView.getSelectionModel().getSelectedItems())); + toolbar.getChildren().add(btnEnable); + + JFXButton btnDisable = new JFXButton(); + btnDisable.getStyleClass().add("jfx-tool-bar-button"); + btnDisable.textFillProperty().bind(Theme.foregroundFillBinding()); + btnDisable.setGraphic(wrap(SVG.close(Theme.foregroundFillBinding(), -1, -1))); + btnDisable.setText(i18n("mods.disable")); + btnDisable.setOnMouseClicked(e -> skinnable.disableSelectedMods(tableView.getSelectionModel().getSelectedItems())); + toolbar.getChildren().add(btnDisable); + + root.setTop(toolbar); + } + + { + SpinnerPane center = new SpinnerPane(); + center.getStyleClass().add("large-spinner-pane"); + center.loadingProperty().bind(skinnable.loadingProperty()); + + tableView.setShowRoot(false); + tableView.setEditable(true); + tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + tableView.setRoot(new RecursiveTreeItem<>(skinnable.getItems(), RecursiveTreeObject::getChildren)); + + JFXTreeTableColumn activeColumn = new JFXTreeTableColumn<>(); + setupCellValueFactory(activeColumn, ModInfoObject::activeProperty); + activeColumn.setCellFactory(c -> new JFXCheckBoxTreeTableCell<>()); + activeColumn.setEditable(true); + activeColumn.setMaxWidth(40); + activeColumn.setMinWidth(40); + + JFXTreeTableColumn fileNameColumn = new JFXTreeTableColumn<>(); + fileNameColumn.setText(i18n("archive.name")); + setupCellValueFactory(fileNameColumn, ModInfoObject::fileNameProperty); + fileNameColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(40).multiply(0.8)); + + JFXTreeTableColumn versionColumn = new JFXTreeTableColumn<>(); + versionColumn.setText(i18n("archive.version")); + versionColumn.setPrefWidth(100); + setupCellValueFactory(versionColumn, ModInfoObject::versionProperty); + versionColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(40).multiply(0.2)); + + tableView.getColumns().setAll(activeColumn, fileNameColumn, versionColumn); + + tableView.setColumnResizePolicy(JFXTreeTableView.CONSTRAINED_RESIZE_POLICY); + center.setContent(tableView); + root.setCenter(center); + } + + getChildren().setAll(root); + } + + private void setupCellValueFactory(JFXTreeTableColumn column, Function> mapper) { + column.setCellValueFactory(new Callback, ObservableValue>() { + @Override + public ObservableValue call(TreeTableColumn.CellDataFeatures param) { + if (column.validateValue(param)) + return mapper.apply(param.getValue().getValue()); + else + return column.getComputedValue(param); + } + }); + } + + public static class ModInfoObject extends RecursiveTreeObject { + private final BooleanProperty active; + private final StringProperty fileName; + private final StringProperty version; + private final ModInfo modInfo; + + public ModInfoObject(ModInfo modInfo) { + this.modInfo = modInfo; + this.active = modInfo.activeProperty(); + this.fileName = new SimpleStringProperty(modInfo.getFileName()); + this.version = new SimpleStringProperty(modInfo.getVersion()); + } + + public BooleanProperty activeProperty() { + return active; + } + + public StringProperty fileNameProperty() { + return fileName; + } + + public StringProperty versionProperty() { + return version; + } + + public ModInfo getModInfo() { + return modInfo; + } + } +} diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 68fcfcf4dc..497bfb9188 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -876,6 +876,14 @@ -fx-stroke-width: 3.0; } +.large-spinner-pane .jfx-spinner { + -jfx-radius: 20; +} + +.large-spinner-pane .jfx-spinner { + -fx-stroke-width: 5.0; +} + .second-spinner { -jfx-radius: 30; } @@ -1028,7 +1036,7 @@ .tree-table-view .column-header .label { -fx-text-fill: #949494; - -fx-padding: 16 0 16 0; + -fx-padding: 8 0 8 0; } .tree-table-view .column-header .arrow, .tree-table-view .column-header .sort-order-dot { @@ -1046,8 +1054,8 @@ .tree-table-view .tree-table-cell { -fx-border-width: 0 0 0 0; - -fx-padding: 16 0 16 0; - -fx-alignment: top-center; + -fx-padding: 8 0 8 0; + /*-fx-alignment: top-center;*/ } .tree-table-view .column-overlay { diff --git a/HMCL/src/main/resources/assets/fxml/download/modpack.fxml b/HMCL/src/main/resources/assets/fxml/download/modpack.fxml index 0a2d6feb47..52d019123b 100644 --- a/HMCL/src/main/resources/assets/fxml/download/modpack.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/modpack.fxml @@ -14,7 +14,7 @@ - + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index f403a75dda..dea8f5bc78 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -66,6 +66,7 @@ account.username=Name archive.author=Authors archive.game_version=Game +archive.name=Name archive.version=Version assets.download=Download assets @@ -252,6 +253,9 @@ mods.add=Add mods mods.add.failed=Failed to add mods %s. mods.add.success=Successfully added mods %s. mods.choose_mod=Choose your mods +mods.enable=Enable +mods.disable=Disable +mods.name=Name mods.remove=Remove datapack=Data packs diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 0ea29d5f81..92ee6a4119 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -65,6 +65,7 @@ account.username=使用者名稱 archive.author=作者 archive.game_version=遊戲版本 +archive.name=名稱 archive.version=版本 assets.download=下載資源 @@ -251,6 +252,8 @@ mods.add=新增模組 mods.add.failed=新增模組 %s 失敗。 mods.add.success=成功新增模組 %s。 mods.choose_mod=選擇模組 +mods.enable=啟用 +mods.disable=禁用 mods.remove=刪除 datapack=資料包 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 67c611e1e3..967ce64178 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -65,6 +65,7 @@ account.username=用户名 archive.author=作者 archive.game_version=游戏版本 +archive.name=名称 archive.version=版本 assets.download=下载资源 @@ -251,6 +252,8 @@ mods.add=添加模组 mods.add.failed=添加模组 %s 失败。 mods.add.success=成功添加模组 %s。 mods.choose_mod=选择模组 +mods.enable=启用 +mods.disable=禁用 mods.remove=删除 datapack=数据包 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java index 71e8991daf..24694d524d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java @@ -124,7 +124,6 @@ public void removeMods(ModInfo... modInfos) throws IOException { for (ModInfo modInfo : modInfos) { Files.deleteIfExists(modInfo.getFile()); } - refreshMods(); } public Path disableMod(Path file) throws IOException { From e3d2a4bf9de291d3482983b10ad0345d0dac6970 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 16 Feb 2019 01:52:37 +0800 Subject: [PATCH 0022/2639] Update JFoenix to fix #523 --- .../java/org/jackhuang/hmcl/Launcher.java | 2 +- .../org/jackhuang/hmcl/setting/Profile.java | 2 +- .../org/jackhuang/hmcl/setting/Profiles.java | 2 +- .../org/jackhuang/hmcl/ui/Controllers.java | 2 +- .../jackhuang/hmcl/ui/DialogController.java | 2 +- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 2 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 2 +- .../hmcl/ui/account/AccountListItemSkin.java | 4 ++-- .../hmcl/ui/account/AddAccountPane.java | 2 +- .../ui/construct/TaskExecutorDialogPane.java | 2 +- .../jackhuang/hmcl/ui/versions/GameList.java | 2 +- .../hmcl/ui/versions/GameListItemSkin.java | 4 ++-- .../hmcl/ui/versions/ModListPage.java | 2 +- .../TaskExecutorDialogWizardDisplayer.java | 2 +- HMCL/src/main/resources/assets/css/root.css | 4 ++++ lib/JFoenix.jar | Bin 589462 -> 658061 bytes 16 files changed, 20 insertions(+), 16 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index e342d40374..87b0e7e99e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.application.Application; import javafx.application.Platform; import javafx.stage.Stage; 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 961ceed7d3..8b12ff90dc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -19,7 +19,7 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.Observable; 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 b38fc8b9be..d925be84b5 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 com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.Observable; import javafx.beans.property.*; 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 3dcd9dc76f..8a2de0b6fe 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.image.Image; 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 51259aacde..ff6ecf94bc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; 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 614ee02958..c03fae6c8c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.*; import javafx.animation.Animation; import javafx.animation.Interpolator; 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 991f4fbc54..bda00a0798 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.scene.image.Image; import javafx.scene.layout.Region; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 0eca64e0e8..c986c317b0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.account; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; @@ -103,7 +103,7 @@ public void fire() { right.getChildren().add(btnRemove); root.setRight(right); - root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;"); + root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 12;"); JFXDepthManager.setDepth(root, 1); getChildren().setAll(root); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index dacc36120e..cbe283d8f4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.account; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.*; import javafx.application.Platform; 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 e7c71463a7..53ebbc398e 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 @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.construct; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXProgressBar; import javafx.application.Platform; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java index 79989649c3..85728e67ef 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.property.*; import javafx.collections.FXCollections; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index a6de9f3f83..b105c02706 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXPopup; import com.jfoenix.controls.JFXRadioButton; @@ -87,7 +87,7 @@ public GameListItemSkin(GameListItem skinnable) { right.getChildren().add(btnManage); root.setRight(right); - root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;"); + root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 12;"); JFXDepthManager.setDepth(root, 1); getChildren().setAll(root); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 9775eba389..3b7a800019 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXTabPane; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ListProperty; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index e837558b26..3fde14e655 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.ui.wizard; -import com.jfoenix.concurrency.JFXUtilities; +import com.jfoenix.utils.JFXUtilities; import javafx.beans.property.StringProperty; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 497bfb9188..93bd3c4c70 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -502,6 +502,10 @@ * * *******************************************************************************/ +.jfx-button { + -jfx-disable-visual-focus: true; +} + .jfx-button-raised { -fx-background-color: -fx-base-color; } diff --git a/lib/JFoenix.jar b/lib/JFoenix.jar index 1672f1ebed5a34b230400c8d57875d659f877aca..4712ea8cdd6b45d643a9ec23e290d52f06cad43f 100644 GIT binary patch delta 415783 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	&1
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�`0G?zyoc6e4D-j|U6PSUEww%+9y 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 WUDhThA@xG)%~*wR5-dOlZSp@&p%zF0 From 9062c2e447d0e160b99ed80ad89d0b8c647e4724 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 17 Feb 2019 13:45:10 +0800 Subject: [PATCH 0023/2639] Display more friendly error message when fail to install library --- .../ui/download/InstallerWizardProvider.java | 16 +++++++++++++++- .../download/ModpackInstallWizardProvider.java | 9 +-------- .../download/VanillaInstallWizardProvider.java | 18 +----------------- .../main/resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../download/game/LibraryDownloadTask.java | 5 +++-- .../jackhuang/hmcl/task/DownloadException.java | 4 +++- 8 files changed, 26 insertions(+), 29 deletions(-) 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 d517816fe1..87f1360f5c 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 @@ -21,12 +21,17 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; +import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; @@ -82,7 +87,7 @@ public void start(Map settings) { @Override public Object finish(Map settings) { settings.put("success_message", i18n("install.success")); - settings.put("failure_message", i18n("install.failed")); + settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next)); Task ret = Task.ofResult("version", () -> version); @@ -114,4 +119,13 @@ public boolean cancel() { return true; } + public static void alertFailureMessage(Exception exception, Runnable next) { + if (exception instanceof LibraryDownloadException) { + Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); + } else if (exception instanceof DownloadException) { + Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); + } else { + Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index a06c758133..5536940abf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -18,21 +18,18 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; -import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.CurseCompletionException; import org.jackhuang.hmcl.mod.MismatchedModpackTypeException; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.mod.UnsupportedModpackException; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; -import org.jackhuang.hmcl.util.StringUtils; import java.io.File; import java.io.FileNotFoundException; @@ -112,12 +109,8 @@ public void onFail(Map settings, Exception exception, Runnable n } else { Controllers.dialog(i18n("modpack.type.curse.tolerable_error"), i18n("install.success"), MessageBox.INFORMATION_MESSAGE, next); } - } else if (exception instanceof LibraryDownloadException) { - Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); - } else if (exception instanceof DownloadException) { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); } else { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); + InstallerWizardProvider.alertFailureMessage(exception, next); } } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index b0105819d1..9a3e6bcbfb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -21,16 +21,11 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.download.RemoteVersion; -import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; -import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; @@ -71,18 +66,7 @@ private Task finishVersionDownloadingAsync(Map settings) { @Override public Object finish(Map settings) { settings.put("success_message", i18n("install.success")); - settings.put("failure_callback", new FailureCallback() { - @Override - public void onFail(Map settings, Exception exception, Runnable next) { - if (exception instanceof LibraryDownloadException) { - Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); - } else if (exception instanceof DownloadException) { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); - } else { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); - } - } - }); + settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> InstallerWizardProvider.alertFailureMessage(exception, next)); return finishVersionDownloadingAsync(settings); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index dea8f5bc78..3cf4d21953 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -126,6 +126,7 @@ input.url=Must be a valid URL. install=Install New Game install.failed=Failed to install install.failed.downloading=Failed to install due to some files not downloaded successfully +install.failed.downloading.detail=Failed to download file: %s install.installer.choose=Choose a %s version install.installer.forge=Forge install.installer.game=Game diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 92ee6a4119..e6ccafb5e3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -125,6 +125,7 @@ input.url=必須為有效連結 install=新增遊戲 install.failed=安裝失敗 install.failed.downloading=安裝失敗,部分文件未能完成下載 +install.failed.downloading.detail=未能下載檔案:%s install.installer.choose=選擇 %s 版本 install.installer.forge=Forge install.installer.game=遊戲 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 967ce64178..1bf87a5135 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -125,6 +125,7 @@ input.url=必须是合法的链接 install=添加游戏 install.failed=安装失败 install.failed.downloading=安装失败,部分文件未能完成下载 +install.failed.downloading.detail=未能下载文件:%s install.installer.choose=选择 %s 版本 install.installer.forge=Forge install.installer.game=游戏 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 ce10254138..fecb40e3f0 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 @@ -20,6 +20,7 @@ import org.jackhuang.hmcl.download.AbstractDependencyManager; import org.jackhuang.hmcl.download.DefaultCacheRepository; import org.jackhuang.hmcl.game.Library; +import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; @@ -88,10 +89,10 @@ public void execute() throws Exception { if (cached) return; if (!isDependentsSucceeded()) { - // Since FileDownloadTask wraps the actual exception with another IOException. + // Since FileDownloadTask wraps the actual exception with DownloadException. // We should extract it letting the error message clearer. Throwable t = task.getLastException(); - if (t.getCause() != null) + if (t instanceof DownloadException) throw new LibraryDownloadException(library, t.getCause()); else throw new LibraryDownloadException(library, t); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java index ca652025b7..d056d9efb0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java @@ -20,12 +20,14 @@ import java.io.IOException; import java.net.URL; +import static java.util.Objects.requireNonNull; + public class DownloadException extends IOException { private final URL url; public DownloadException(URL url, Throwable cause) { - super("Unable to download " + url + ", " + cause.getMessage(), cause); + super("Unable to download " + url + ", " + cause.getMessage(), requireNonNull(cause)); this.url = url; } From 88f6fd196587476450b64cc7a31e1557f7b1b6ed Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 17 Feb 2019 13:57:49 +0800 Subject: [PATCH 0024/2639] Set cursor in button to hand by default --- .../org/jackhuang/hmcl/ui/ListPageSkin.java | 4 ++-- .../org/jackhuang/hmcl/ui/SettingsView.java | 10 ++++----- .../ui/construct/AdvancedListItemSkin.java | 4 ++-- .../hmcl/ui/construct/IconedItem.java | 2 +- .../hmcl/ui/construct/PopupMenu.java | 2 +- .../hmcl/ui/decorator/DecoratorSkin.java | 22 +++++++++---------- .../decorator/DecoratorWizardDisplayer.java | 2 +- .../hmcl/ui/versions/GameListSkin.java | 2 +- .../hmcl/ui/versions/ModListPageSkin.java | 2 +- HMCL/src/main/resources/assets/css/root.css | 3 ++- 10 files changed, 27 insertions(+), 26 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java index ae084d9f9b..874fc743fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java @@ -70,7 +70,7 @@ public ListPageSkin(ListPage skinnable) { JFXButton btnAdd = new JFXButton(); FXUtils.setLimitWidth(btnAdd, 40); FXUtils.setLimitHeight(btnAdd, 40); - btnAdd.getStyleClass().setAll("jfx-button-raised-round"); + btnAdd.getStyleClass().add("jfx-button-raised-round"); btnAdd.setButtonType(JFXButton.ButtonType.RAISED); btnAdd.setGraphic(SVG.plus(Theme.whiteFillBinding(), -1, -1)); btnAdd.setOnMouseClicked(e -> skinnable.add()); @@ -78,7 +78,7 @@ public ListPageSkin(ListPage skinnable) { JFXButton btnRefresh = new JFXButton(); FXUtils.setLimitWidth(btnRefresh, 40); FXUtils.setLimitHeight(btnRefresh, 40); - btnRefresh.getStyleClass().setAll("jfx-button-raised-round"); + btnRefresh.getStyleClass().add("jfx-button-raised-round"); btnRefresh.setButtonType(JFXButton.ButtonType.RAISED); btnRefresh.setGraphic(SVG.refresh(Theme.whiteFillBinding(), -1, -1)); btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java index 07638486c5..fc9fc75133 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java @@ -83,7 +83,7 @@ public SettingsView() { lblUpdate = new Label(i18n("update")); lblUpdateSub = new Label(); - lblUpdateSub.getStyleClass().setAll("subtitle-label"); + lblUpdateSub.getStyleClass().add("subtitle-label"); headerLeft.getChildren().setAll(lblUpdate, lblUpdateSub); updatePane.setHeaderLeft(headerLeft); @@ -92,7 +92,7 @@ public SettingsView() { { btnUpdate = new JFXButton(); btnUpdate.setOnMouseClicked(e -> onUpdate()); - btnUpdate.getStyleClass().setAll("toggle-icon4"); + btnUpdate.getStyleClass().add("toggle-icon4"); btnUpdate.setGraphic(SVG.update(Theme.blackFillBinding(), 20, 20)); updatePane.setHeaderRight(btnUpdate); @@ -124,7 +124,7 @@ public SettingsView() { Label help = new Label(i18n("help")); Label helpSubtitle = new Label(i18n("help.detail")); - helpSubtitle.getStyleClass().setAll("subtitle-label"); + helpSubtitle.getStyleClass().add("subtitle-label"); headerLeft.getChildren().setAll(help, helpSubtitle); updatePane.setLeft(headerLeft); @@ -133,7 +133,7 @@ public SettingsView() { { JFXButton btnExternal = new JFXButton(); btnExternal.setOnMouseClicked(e -> onHelp()); - btnExternal.getStyleClass().setAll("toggle-icon4"); + btnExternal.getStyleClass().add("toggle-icon4"); btnExternal.setGraphic(SVG.openInNew(Theme.blackFillBinding(), -1, -1)); updatePane.setRight(btnExternal); @@ -337,7 +337,7 @@ public SettingsView() { { JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export")); logButton.setOnMouseClicked(e -> onExportLogs()); - logButton.getStyleClass().setAll("jfx-button-border"); + logButton.getStyleClass().add("jfx-button-border"); logPane.setHeaderRight(logButton); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItemSkin.java index 3e524807b0..ce451fd900 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItemSkin.java @@ -83,7 +83,7 @@ public AdvancedListItemSkin(AdvancedListItem skinnable) { HBox right = new HBox(); right.setAlignment(Pos.CENTER); right.setMouseTransparent(true); - right.getStyleClass().setAll("toggle-icon4"); + right.getStyleClass().add("toggle-icon4"); FXUtils.setLimitWidth(right, 40); FXUtils.onChangeAndOperate(skinnable.rightGraphicProperty(), newGraphic -> { @@ -99,7 +99,7 @@ public AdvancedListItemSkin(AdvancedListItem skinnable) { visible -> root.setRight(visible ? right : null)); stackPane.setStyle("-fx-padding: 10 16 10 16;"); - stackPane.getStyleClass().setAll("transparent"); + stackPane.getStyleClass().add("transparent"); stackPane.setPickOnBounds(false); stackPane.getChildren().setAll(root); 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 fe2d9dd551..bf718fce9b 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 @@ -45,7 +45,7 @@ private static HBox createHBox(Node icon) { hBox.getChildren().add(icon); } - hBox.getStyleClass().setAll("iconed-item-container"); + hBox.getStyleClass().add("iconed-item-container"); Label textLabel = new Label(); textLabel.setId("label"); textLabel.setMouseTransparent(true); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java index cbe7b667b4..5173d663d4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java @@ -64,7 +64,7 @@ protected Skin createDefaultSkin() { public static Node wrapPopupMenuItem(Node node) { StackPane pane = new StackPane(); pane.getChildren().setAll(node); - pane.getStyleClass().setAll("menu-container"); + pane.getStyleClass().add("menu-container"); node.setMouseTransparent(true); return new RipplerContainer(pane); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index f205024472..a4aac7fdce 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -73,7 +73,7 @@ public DecoratorSkin(Decorator control) { Decorator skinnable = getSkinnable(); BorderPane root = new BorderPane(); - root.getStyleClass().setAll("jfx-decorator", "resize-border"); + root.getStyleClass().addAll("jfx-decorator", "resize-border"); root.setPrefHeight(519); root.setPrefWidth(800); root.setMaxHeight(Region.USE_PREF_SIZE); @@ -83,7 +83,7 @@ public DecoratorSkin(Decorator control) { StackPane drawerWrapper = new StackPane(); skinnable.setDrawerWrapper(drawerWrapper); - drawerWrapper.getStyleClass().setAll("jfx-decorator-drawer"); + drawerWrapper.getStyleClass().add("jfx-decorator-drawer"); drawerWrapper.backgroundProperty().bind(skinnable.backgroundProperty()); FXUtils.setOverflowHidden(drawerWrapper, true); { @@ -92,10 +92,10 @@ public DecoratorSkin(Decorator control) { { BorderPane leftRootPane = new BorderPane(); FXUtils.setLimitWidth(leftRootPane, 200); - leftRootPane.getStyleClass().setAll("jfx-decorator-content-container"); + leftRootPane.getStyleClass().add("jfx-decorator-content-container"); StackPane drawerContainer = new StackPane(); - drawerContainer.getStyleClass().setAll("gray-background"); + drawerContainer.getStyleClass().add("gray-background"); Bindings.bindContent(drawerContainer.getChildren(), skinnable.drawerProperty()); leftRootPane.setCenter(drawerContainer); @@ -111,7 +111,7 @@ public DecoratorSkin(Decorator control) { { contentPlaceHolder = new StackPane(); - contentPlaceHolder.getStyleClass().setAll("jfx-decorator-content-container"); + contentPlaceHolder.getStyleClass().add("jfx-decorator-content-container"); contentPlaceHolder.backgroundProperty().bind(skinnable.contentBackgroundProperty()); FXUtils.setOverflowHidden(contentPlaceHolder, true); Bindings.bindContent(contentPlaceHolder.getChildren(), skinnable.contentProperty()); @@ -189,14 +189,14 @@ public void onChanged(Change c) { { JFXButton backNavButton = new JFXButton(); backNavButton.setGraphic(SVG.back(Theme.foregroundFillBinding(), -1, -1)); - backNavButton.getStyleClass().setAll("jfx-decorator-button"); + backNavButton.getStyleClass().add("jfx-decorator-button"); backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty()); backNavButton.visibleProperty().bind(skinnable.canBackProperty()); closeNavButton = new JFXButton(); closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - closeNavButton.getStyleClass().setAll("jfx-decorator-button"); + closeNavButton.getStyleClass().add("jfx-decorator-button"); closeNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); closeNavButton.onActionProperty().bind(skinnable.onCloseNavButtonActionProperty()); @@ -219,7 +219,7 @@ public void onChanged(Change c) { VBox navCenter = new VBox(); navCenter.setAlignment(Pos.CENTER_LEFT); Label titleLabel = new Label(); - titleLabel.getStyleClass().setAll("jfx-decorator-title"); + titleLabel.getStyleClass().add("jfx-decorator-title"); titleLabel.textProperty().bind(skinnable.drawerTitleProperty()); navCenter.getChildren().setAll(titleLabel); navBar.setCenter(navCenter); @@ -228,7 +228,7 @@ public void onChanged(Change c) { navRight.setAlignment(Pos.CENTER_RIGHT); refreshNavButton = new JFXButton(); refreshNavButton.setGraphic(SVG.refresh(Theme.foregroundFillBinding(), -1, -1)); - refreshNavButton.getStyleClass().setAll("jfx-decorator-button"); + refreshNavButton.getStyleClass().add("jfx-decorator-button"); refreshNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); refreshNavButton.onActionProperty().bind(skinnable.onRefreshNavButtonActionProperty()); refreshNavButton.visibleProperty().bind(skinnable.canRefreshProperty()); @@ -251,12 +251,12 @@ public void onChanged(Change c) { StackPane pane = new StackPane(minus); pane.setAlignment(Pos.CENTER); btnMin.setGraphic(pane); - btnMin.getStyleClass().setAll("jfx-decorator-button"); + btnMin.getStyleClass().add("jfx-decorator-button"); btnMin.setOnAction(e -> skinnable.minimize()); JFXButton btnClose = new JFXButton(); btnClose.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - btnClose.getStyleClass().setAll("jfx-decorator-button"); + btnClose.getStyleClass().add("jfx-decorator-button"); btnClose.setOnAction(e -> skinnable.close()); buttonsContainer.getChildren().setAll(separator, btnMin, btnClose); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java index a8826b56bb..0bc6589570 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java @@ -52,7 +52,7 @@ public DecoratorWizardDisplayer(WizardProvider provider, String category) { wizardController.setProvider(provider); wizardController.onStart(); - getStyleClass().setAll("white-background"); + getStyleClass().add("white-background"); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java index c011b27745..faae0ca743 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListSkin.java @@ -50,7 +50,7 @@ public GameListSkin(GameList skinnable) { { HBox toolbar = new HBox(); - toolbar.getStyleClass().setAll("jfx-tool-bar-second"); + toolbar.getStyleClass().add("jfx-tool-bar-second"); JFXDepthManager.setDepth(toolbar, 1); toolbar.setPickOnBounds(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 224d526733..f247f61493 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -58,7 +58,7 @@ public ModListPageSkin(ModListPage skinnable) { { HBox toolbar = new HBox(); - toolbar.getStyleClass().setAll("jfx-tool-bar-second"); + toolbar.getStyleClass().add("jfx-tool-bar-second"); JFXDepthManager.setDepth(toolbar, 1); toolbar.setPickOnBounds(false); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 93bd3c4c70..9208725e91 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -346,7 +346,7 @@ } .jfx-tool-bar .jfx-decorator-button { - -fx-cursor: head; + -fx-cursor: hand; } .jfx-tool-bar Label { @@ -504,6 +504,7 @@ .jfx-button { -jfx-disable-visual-focus: true; + -fx-cursor: hand; } .jfx-button-raised { From a3dc7798e78b4e5635aaf8ed918b106242236dbc Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 17 Feb 2019 14:01:05 +0800 Subject: [PATCH 0025/2639] fetch Forge remote version list only from BMCLAPI --- .../hmcl/ui/download/VersionsPage.java | 2 +- .../download/BMCLAPIDownloadProvider.java | 4 +- .../download/DefaultDependencyManager.java | 2 +- .../hmcl/download/MojangDownloadProvider.java | 6 +- .../jackhuang/hmcl/download/VersionList.java | 31 +++ .../download/forge/ForgeBMCLVersionList.java | 185 ++++++++++++++++++ .../hmcl/download/forge/ForgeInstallTask.java | 90 ++++----- .../download/forge/ForgeOldInstallTask.java | 94 +++++++++ .../hmcl/download/forge/ForgeVersionList.java | 3 +- .../jackhuang/hmcl/util/SimpleMultimap.java | 7 + 10 files changed, 362 insertions(+), 62 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java 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 3da241fd93..bab0e59a55 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 @@ -123,7 +123,7 @@ private List loadVersions() { @Override public void refresh() { getChildren().setAll(spinner); - executor = versionList.refreshAsync(downloadProvider).finalized((variables, isDependentsSucceeded) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded) -> { if (isDependentsSucceeded) { List items = loadVersions(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java index efe9025e13..123487c55f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.download; -import org.jackhuang.hmcl.download.forge.ForgeVersionList; +import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList; import org.jackhuang.hmcl.download.game.GameVersionList; import org.jackhuang.hmcl.download.liteloader.LiteLoaderBMCLVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; @@ -44,7 +44,7 @@ public VersionList getVersionListById(String id) { case "game": return GameVersionList.INSTANCE; case "forge": - return ForgeVersionList.INSTANCE; + return ForgeBMCLVersionList.INSTANCE; case "liteloader": return LiteLoaderBMCLVersionList.INSTANCE; case "optifine": diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 7be09a437e..d121b4b33a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -90,7 +90,7 @@ public Task checkLibraryCompletionAsync(Version version) { @Override public Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); - return versionList.loadAsync(getDownloadProvider()) + return versionList.loadAsync(gameVersion, getDownloadProvider()) .then(variables -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) .orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion)))); } 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 e4ce8d7296..0bc60b0bb8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList; import org.jackhuang.hmcl.download.forge.ForgeVersionList; import org.jackhuang.hmcl.download.game.GameVersionList; import org.jackhuang.hmcl.download.liteloader.LiteLoaderVersionList; @@ -44,7 +45,7 @@ public VersionList getVersionListById(String id) { case "game": return GameVersionList.INSTANCE; case "forge": - return ForgeVersionList.INSTANCE; + return ForgeBMCLVersionList.INSTANCE; case "liteloader": return LiteLoaderVersionList.INSTANCE; case "optifine": @@ -56,6 +57,7 @@ public VersionList getVersionListById(String id) { @Override public String injectURL(String baseURL) { - return baseURL; + return baseURL + .replaceFirst("https?://files\\.minecraftforge\\.net/maven", "https://bmclapi2.bangbang93.com/maven"); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index c544269364..e00a8abc5c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -46,6 +46,14 @@ public boolean isLoaded() { return !versions.isEmpty(); } + /** + * True if the version list that contains the remote versions which depends on the specific game version has been loaded. + * @param gameVersion the remote version depends on + */ + public boolean isLoaded(String gameVersion) { + return !versions.get(gameVersion).isEmpty(); + } + public abstract boolean hasType(); protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); @@ -56,6 +64,15 @@ public boolean isLoaded() { */ public abstract Task refreshAsync(DownloadProvider downloadProvider); + /** + * @param gameVersion the remote version depends on + * @param downloadProvider DownloadProvider + * @return the task to reload the remote version list. + */ + public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { + return refreshAsync(downloadProvider); + } + public Task loadAsync(DownloadProvider downloadProvider) { return Task.ofThen(variables -> { lock.readLock().lock(); @@ -70,6 +87,20 @@ public Task loadAsync(DownloadProvider downloadProvider) { }); } + public Task loadAsync(String gameVersion, DownloadProvider downloadProvider) { + return Task.ofThen(variables -> { + lock.readLock().lock(); + boolean loaded; + + try { + loaded = isLoaded(gameVersion); + } finally { + lock.readLock().unlock(); + } + return loaded ? null : refreshAsync(gameVersion, downloadProvider); + }); + } + protected Collection getVersionsImpl(String gameVersion) { lock.readLock().lock(); try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java new file mode 100644 index 0000000000..fca99043eb --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -0,0 +1,185 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.download.forge; + +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Immutable; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.gson.Validation; +import org.jackhuang.hmcl.util.io.NetworkUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public final class ForgeBMCLVersionList extends VersionList { + + public static final ForgeBMCLVersionList INSTANCE = new ForgeBMCLVersionList(); + + private ForgeBMCLVersionList() { + } + + @Override + public boolean hasType() { + return false; + } + + @Override + public Task loadAsync(DownloadProvider downloadProvider) { + throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); + } + + @Override + public Task refreshAsync(DownloadProvider downloadProvider) { + throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); + } + + @Override + public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { + final GetTask task = new GetTask(NetworkUtils.toURL("https://bmclapi2.bangbang93.com/forge/minecraft/" + gameVersion)); + return new Task() { + @Override + public Collection getDependents() { + return Collections.singleton(task); + } + + @Override + public void execute() { + lock.writeLock().lock(); + + try { + List forgeVersions = JsonUtils.GSON.fromJson(task.getResult(), new TypeToken>() { + }.getType()); + versions.clear(gameVersion); + if (forgeVersions == null) return; + for (ForgeVersion version : forgeVersions) { + if (version == null) + continue; + String jar = null; + for (ForgeVersion.File file : version.getFiles()) + if ("installer".equals(file.getCategory())) { + String classifier = gameVersion + "-" + version.getVersion() + + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); + String fileName = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat(); + jar = "https://bmclapi2.bangbang93.com/maven/net/minecraftforge/forge/" + classifier + "/" + fileName; + } + + if (jar == null) + continue; + versions.put(gameVersion, new ForgeRemoteVersion( + version.getGameVersion(), version.getVersion(), jar + )); + } + } finally { + lock.writeLock().unlock(); + } + } + }; + } + + @Immutable + public static final class ForgeVersion implements Validation { + + private final String branch; + private final String mcversion; + private final String version; + private final int build; + private final List files; + + /** + * No-arg constructor for Gson. + */ + @SuppressWarnings("unused") + public ForgeVersion() { + this(null, null, null, 0, null); + } + + public ForgeVersion(String branch, String mcversion, String version, int build, List files) { + this.branch = branch; + this.mcversion = mcversion; + this.version = version; + this.build = build; + this.files = files; + } + + public String getBranch() { + return branch; + } + + public String getGameVersion() { + return mcversion; + } + + public String getVersion() { + return version; + } + + public int getBuild() { + return build; + } + + public List getFiles() { + return files; + } + + @Override + public void validate() throws JsonParseException { + if (files == null) + throw new JsonParseException("ForgeVersion files cannot be null"); + if (version == null) + throw new JsonParseException("ForgeVersion version cannot be null"); + if (mcversion == null) + throw new JsonParseException("ForgeVersion mcversion cannot be null"); + } + + @Immutable + public static final class File { + private final String format; + private final String category; + private final String hash; + + public File() { + this("", "", ""); + } + + public File(String format, String category, String hash) { + this.format = format; + this.category = category; + this.hash = hash; + } + + public String getFormat() { + return format; + } + + public String getCategory() { + return category; + } + + public String getHash() { + return hash; + } + } + } +} 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 7c056d0c66..2843c56b3d 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 @@ -18,24 +18,17 @@ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.game.Library; -import org.jackhuang.hmcl.game.SimpleVersionProvider; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskResult; -import org.jackhuang.hmcl.util.gson.JsonUtils; -import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jackhuang.hmcl.util.versioning.VersionNumber; -import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * @@ -45,31 +38,48 @@ 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 Path installer; private final ForgeRemoteVersion remote; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); - - private Task downloadFileTask() { - return new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), installer); - } + private Task dependent; + private TaskResult dependency; public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; this.version = version; this.remote = remoteVersion; + } + + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void preExecute() throws Exception { + installer = Files.createTempFile("forge-installer", ".jar"); + + dependent = new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), installer.toFile()); + } - dependents.add(downloadFileTask()); + @Override + public boolean doPostExecute() { + return true; + } + + @Override + public void postExecute() throws Exception { + Files.deleteIfExists(installer); + setResult(dependency.getResult()); } @Override public Collection getDependents() { - return dependents; + return Collections.singleton(dependent); } @Override - public List getDependencies() { - return dependencies; + public Collection getDependencies() { + return Collections.singleton(dependency); } @Override @@ -83,38 +93,10 @@ public boolean isRelyingOnDependencies() { } @Override - public void execute() throws Exception { - try (ZipFile zipFile = new ZipFile(installer)) { - InputStream stream = zipFile.getInputStream(zipFile.getEntry("install_profile.json")); - if (stream == null) - throw new IOException("Malformed forge installer file, install_profile.json does not exist."); - String json = IOUtils.readFullyAsString(stream); - ForgeInstallProfile installProfile = JsonUtils.fromNonNullJson(json, ForgeInstallProfile.class); - - // unpack the universal jar in the installer file. - Library forgeLibrary = Library.fromName(installProfile.getInstall().getPath()); - File forgeFile = dependencyManager.getGameRepository().getLibraryFile(version, forgeLibrary); - if (!FileUtils.makeFile(forgeFile)) - throw new IOException("Cannot make directory " + forgeFile.getParent()); - - ZipEntry forgeEntry = zipFile.getEntry(installProfile.getInstall().getFilePath()); - try (InputStream is = zipFile.getInputStream(forgeEntry); OutputStream os = new FileOutputStream(forgeFile)) { - IOUtils.copyTo(is, os); - } - - // resolve the version - SimpleVersionProvider provider = new SimpleVersionProvider(); - provider.addVersion(version); - - setResult(installProfile.getVersionInfo() - .setInheritsFrom(version.getId()) - .resolve(provider).setJar(null) - .setId(version.getId()).setLogging(Collections.emptyMap())); - - dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo())); - } - - if (!installer.delete()) - throw new IOException("Unable to delete installer file" + installer); + public void execute() { + if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) + dependency = new ForgeNewInstallTask(dependencyManager, version, installer); + else + dependency = new ForgeOldInstallTask(dependencyManager, version, installer); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java new file mode 100644 index 0000000000..fca62abec2 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java @@ -0,0 +1,94 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.download.forge; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.game.*; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.io.IOUtils; + +import java.io.*; +import java.nio.file.Path; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class ForgeOldInstallTask extends TaskResult { + + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final Path installer; + private final List dependencies = new LinkedList<>(); + + public ForgeOldInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { + this.dependencyManager = dependencyManager; + this.version = version; + this.installer = installer; + } + + @Override + public List getDependencies() { + return dependencies; + } + + @Override + public String getId() { + return "version"; + } + + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void execute() throws Exception { + try (ZipFile zipFile = new ZipFile(installer.toFile())) { + InputStream stream = zipFile.getInputStream(zipFile.getEntry("install_profile.json")); + if (stream == null) + throw new IOException("Malformed forge installer file, install_profile.json does not exist."); + String json = IOUtils.readFullyAsString(stream); + ForgeInstallProfile installProfile = JsonUtils.fromNonNullJson(json, ForgeInstallProfile.class); + + // unpack the universal jar in the installer file. + Library forgeLibrary = Library.fromName(installProfile.getInstall().getPath()); + File forgeFile = dependencyManager.getGameRepository().getLibraryFile(version, forgeLibrary); + if (!FileUtils.makeFile(forgeFile)) + throw new IOException("Cannot make directory " + forgeFile.getParent()); + + ZipEntry forgeEntry = zipFile.getEntry(installProfile.getInstall().getFilePath()); + try (InputStream is = zipFile.getInputStream(forgeEntry); OutputStream os = new FileOutputStream(forgeFile)) { + IOUtils.copyTo(is, os); + } + + // resolve the version + SimpleVersionProvider provider = new SimpleVersionProvider(); + provider.addVersion(version); + + setResult(installProfile.getVersionInfo() + .setInheritsFrom(version.getId()) + .resolve(provider).setJar(null) + .setId(version.getId()).setLogging(Collections.emptyMap())); + + dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo())); + } + } +} 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 d367ef663a..3f9070d08e 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 @@ -47,12 +47,11 @@ public boolean hasType() { @Override public Task refreshAsync(DownloadProvider downloadProvider) { final GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(FORGE_LIST))); - final List dependents = Collections.singletonList(task); return new Task() { @Override public Collection getDependents() { - return dependents; + return Collections.singleton(task); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/SimpleMultimap.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/SimpleMultimap.java index eee95919f0..be7c2217f1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/SimpleMultimap.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/SimpleMultimap.java @@ -88,4 +88,11 @@ public boolean removeValue(K key, V value) { public void clear() { map.clear(); } + + public void clear(K key) { + if (map.containsKey(key)) + map.get(key).clear(); + else + map.put(key, valuer.get()); + } } From c6f1aa21c5f136963ba077ab4ee0606f6c0b0547 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Tue, 19 Feb 2019 18:56:36 +0800 Subject: [PATCH 0026/2639] Log exception in login pane --- .../java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java index 3a758bed56..4e739e05ee 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java @@ -31,6 +31,9 @@ import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; import java.util.function.Consumer; +import java.util.logging.Level; + +import static org.jackhuang.hmcl.util.Logging.LOG; public class AccountLoginPane extends StackPane { private final Account oldAccount; @@ -64,6 +67,7 @@ private void onAccept() { fireEvent(new DialogCloseEvent()); progressBar.setVisible(false); }, e -> { + LOG.log(Level.INFO, "Failed to login with password: " + oldAccount, e); if (e instanceof NoSelectedCharacterException) { fireEvent(new DialogCloseEvent()); } else { From d0dd23fa147ee3b3cc44ffc7073b4c6803d8dea9 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 19 Feb 2019 19:36:23 +0800 Subject: [PATCH 0027/2639] Fix compilation error along with openjfx --- .../hmcl/ui/construct/RipplerContainer.java | 67 ++----------------- 1 file changed, 4 insertions(+), 63 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java index 3efdb873b9..b1e274037f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXRippler; -import javafx.animation.Transition; import javafx.beans.DefaultProperty; import javafx.beans.InvalidationListener; import javafx.beans.NamedArg; @@ -64,68 +63,28 @@ protected Node getMask() { mask.resize(buttonContainer.getWidth() - buttonContainer.snappedRightInset() - buttonContainer.snappedLeftInset(), buttonContainer.getHeight() - buttonContainer.snappedBottomInset() - buttonContainer.snappedTopInset()); return mask; } - - @Override - protected void initListeners() { - this.ripplerPane.setOnMousePressed(event -> { - if (releaseManualRippler != null) - releaseManualRippler.run(); - releaseManualRippler = null; - createRipple(event.getX(), event.getY()); - }); - } }; - private Transition clickedAnimation; private final CornerRadii defaultRadii = new CornerRadii(3); - private Runnable releaseManualRippler; public RipplerContainer(@NamedArg("container") Node container) { setContainer(container); getStyleClass().add(DEFAULT_STYLE_CLASS); buttonContainer.getChildren().add(buttonRippler); - setOnMousePressed(event -> { - if (clickedAnimation != null) { - clickedAnimation.setRate(1); - clickedAnimation.play(); - } - }); - setOnMouseReleased(event -> { - if (clickedAnimation != null) { - clickedAnimation.setRate(-1); - clickedAnimation.play(); - } - }); focusedProperty().addListener((a, b, newValue) -> { if (newValue) { if (!isPressed()) - buttonRippler.showOverlay(); + buttonRippler.setOverlayVisible(true); } else { - buttonRippler.hideOverlay(); + buttonRippler.setOverlayVisible(false); } }); - pressedProperty().addListener(o -> buttonRippler.hideOverlay()); + pressedProperty().addListener(o -> buttonRippler.setOverlayVisible(false)); setPickOnBounds(false); buttonContainer.setPickOnBounds(false); - buttonContainer.shapeProperty().bind(shapeProperty()); - buttonContainer.borderProperty().bind(borderProperty()); - buttonContainer.backgroundProperty().bind(Bindings.createObjectBinding(() -> { - if (getBackground() == null || isJavaDefaultBackground(getBackground()) || isJavaDefaultClickedBackground(getBackground())) - setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, defaultRadii, null))); - - try { - return new Background(new BackgroundFill(getBackground() != null ? getBackground().getFills().get(0).getFill() : Color.TRANSPARENT, - getBackground() != null ? getBackground().getFills().get(0).getRadii() : defaultRadii, Insets.EMPTY)); - } catch (Exception e) { - return getBackground(); - } - }, backgroundProperty())); - - ripplerFillProperty().addListener((a, b, newValue) -> buttonRippler.setRipplerFill(newValue)); - if (getBackground() == null || isJavaDefaultBackground(getBackground())) - setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, defaultRadii, null))); + buttonRippler.ripplerFillProperty().bind(ripplerFillProperty()); containerProperty().addListener(o -> updateChildren()); updateChildren(); @@ -153,24 +112,6 @@ protected void updateChildren() { getChildren().get(i).setPickOnBounds(false); } - private boolean isJavaDefaultBackground(Background background) { - try { - String firstFill = background.getFills().get(0).getFill().toString(); - return "0xffffffba".equals(firstFill) || "0xffffffbf".equals(firstFill) || "0xffffffbd".equals(firstFill); - } catch (Exception e) { - return false; - } - } - - private boolean isJavaDefaultClickedBackground(Background background) { - try { - String firstFill = background.getFills().get(0).getFill().toString(); - return "0x039ed3ff".equals(firstFill); - } catch (Exception e) { - return false; - } - } - public Node getContainer() { return container.get(); } From c698eaac6fdda4655b7097d0c9c6bb37d8f3d022 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 19 Feb 2019 19:38:37 +0800 Subject: [PATCH 0028/2639] Add sponsor information --- .../org/jackhuang/hmcl/ui/SettingsPage.java | 5 +++ .../org/jackhuang/hmcl/ui/SettingsView.java | 15 +++++++ .../hmcl/ui/download/VersionsPage.java | 16 +++++-- HMCL/src/main/resources/assets/css/root.css | 10 +++++ .../assets/fxml/download/versions.fxml | 43 +++++++++++-------- .../resources/assets/lang/I18N.properties | 3 ++ .../resources/assets/lang/I18N_zh.properties | 3 ++ .../assets/lang/I18N_zh_CN.properties | 3 ++ 8 files changed, 78 insertions(+), 20 deletions(-) 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 75bf402b58..7adb5bbc69 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -247,4 +247,9 @@ protected void onExportLogs() { protected void onHelp() { FXUtils.openLink(Metadata.HELP_URL); } + + @Override + protected void onSponsor() { + FXUtils.openLink("https://hmcl.huangyuhui.net/api/redirect/sponsor"); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java index fc9fc75133..e56f6d46d2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java @@ -21,6 +21,7 @@ import javafx.geometry.HPos; import javafx.geometry.Pos; import javafx.geometry.VPos; +import javafx.scene.Cursor; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.*; @@ -75,6 +76,19 @@ public SettingsView() { { ComponentList settingsPane = new ComponentList(); { + { + StackPane sponsorPane = new StackPane(); + sponsorPane.setCursor(Cursor.HAND); + sponsorPane.setOnMouseClicked(e -> onSponsor()); + { + Label label = new Label(i18n("sponsor.hmcl")); + label.setWrapText(true); + label.prefWidthProperty().bind(sponsorPane.widthProperty()); + sponsorPane.getChildren().add(label); + } + settingsPane.getContent().add(sponsorPane); + } + ComponentSublist updatePane = new ComponentSublist(); updatePane.setTitle(i18n("update")); updatePane.setHasSubtitle(true); @@ -491,4 +505,5 @@ public SettingsView() { protected abstract void onUpdate(); protected abstract void onHelp(); protected abstract void onExportLogs(); + protected abstract void onSponsor(); } 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 bab0e59a55..13b4d9c562 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 @@ -25,6 +25,7 @@ import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.fxml.FXML; +import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -43,7 +44,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; -public final class VersionsPage extends StackPane implements WizardPage, Refreshable { +public final class VersionsPage extends BorderPane implements WizardPage, Refreshable { private final String gameVersion; private final DownloadProvider downloadProvider; private final String libraryId; @@ -59,6 +60,8 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh @FXML private StackPane emptyPane; @FXML + private StackPane root; + @FXML private JFXCheckBox chkRelease; @FXML private JFXCheckBox chkSnapshot; @@ -69,7 +72,7 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh @FXML private VBox centrePane; - private final TransitionHandler transitionHandler = new TransitionHandler(this); + private final TransitionHandler transitionHandler; private final VersionList versionList; private TaskExecutor executor; @@ -83,6 +86,8 @@ public VersionsPage(WizardController controller, String title, String gameVersio FXUtils.loadFXML(this, "/assets/fxml/download/versions.fxml"); + transitionHandler = new TransitionHandler(root); + if (versionList.hasType()) { centrePane.getChildren().setAll(checkPane, list); } else @@ -122,7 +127,7 @@ private List loadVersions() { @Override public void refresh() { - getChildren().setAll(spinner); + transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded) -> { if (isDependentsSucceeded) { List items = loadVersions(); @@ -169,4 +174,9 @@ private void onRefresh() { @FXML private void onBack() { controller.onPrev(true); } + + @FXML + private void onSponsor() { + FXUtils.openLink("https://hmcl.huangyuhui.net/api/redirect/bmclapi_sponsor"); + } } diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 9208725e91..a6ef08dbae 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -132,6 +132,16 @@ -fx-fill: -fx-base-darker-color; } +.sponsor-pane { + -fx-padding: 16; + -fx-background-color: white; + -fx-cursor: hand; +} + +.sponsor-pane .label { + -fx-wrap-text: true; +} + /******************************************************************************* * * * JFX Tab Pane * diff --git a/HMCL/src/main/resources/assets/fxml/download/versions.fxml b/HMCL/src/main/resources/assets/fxml/download/versions.fxml index 53f38ea408..c49f0444bc 100644 --- a/HMCL/src/main/resources/assets/fxml/download/versions.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/versions.fxml @@ -5,22 +5,31 @@ - - - - - - - - - - - - - - + + + + +

+ + + + + + + + + + + + + + + + +
diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 3cf4d21953..69c7b3d76e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -369,6 +369,9 @@ settings.type.global.manage=Global Game Settings settings.type.global.edit=Configure global game settings settings.type.special.enable=Enable specialized settings for this game +sponsor.bmclapi=To obtain a stable download service, please consider support BMCLAPI. Click here for more information +sponsor.hmcl=HMCL is a free, open source Minecraft launcher the enables users to easily manage multiple, separate installations of Minecraft. We're using Afdian so that we can continue to pay for our hosting and project development. Click here for more information. + update=Update update.channel.dev=Update to development version update.channel.stable=Update to stable version diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index e6ccafb5e3..a60b08d16b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -367,6 +367,9 @@ settings.type.global.manage=全域遊戲設定 settings.type.global.edit=編輯全域遊戲設定 settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本) +sponsor.bmclapi=請贊助 BMCLAPI 從而獲得穩定高速的下載服務,點擊此處查閱詳細訊息。 +sponsor.hmcl=HMCL 是一個免費、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、運行遊戲。您的贊助將幫助 HMCL 獲得更好的發展、支持穩定高速的遊戲安裝與文件下載服務。點擊此處查閱更多詳細訊息。 + update=啟動器更新 update.channel.dev=更新到開發版 update.channel.stable=更新到推薦版本 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 1bf87a5135..d743405e72 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -367,6 +367,9 @@ settings.type.global.manage=全局游戏设置 settings.type.global.edit=编辑全局版本设置 settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本) +sponsor.bmclapi=请赞助 BMCLAPI 从而获得稳定高速的下载服务,点击此处查阅详细信息。 +sponsor.hmcl=HMCL 是一个免费、开源的 Minecraft 启动器,允许玩家方便快捷地安装、管理、运行游戏。您的赞助将帮助 HMCL 获得更好的发展、支持稳定高速的游戏安装与文件下载服务。点击此处查阅更多详细信息。 + update=启动器更新 update.channel.dev=更新到开发版 update.channel.stable=更新到推荐版本 From d8aa989cc410cca498ae2ee20f305c77d8c46c12 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 19 Feb 2019 23:15:45 +0800 Subject: [PATCH 0029/2639] Fix #532 --- .../main/java/org/jackhuang/hmcl/auth/yggdrasil/User.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/User.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/User.java index dfff36e5fb..d44eb8a39e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/User.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/User.java @@ -21,6 +21,7 @@ import java.util.Map; +import com.google.gson.annotations.JsonAdapter; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.Validation; @@ -36,13 +37,14 @@ public final class User implements Validation { private final String id; @Nullable + @JsonAdapter(PropertyMapSerializer.class) private final Map properties; public User(String id) { this(id, null); } - public User(String id, Map properties) { + public User(String id, @Nullable Map properties) { this.id = id; this.properties = properties; } @@ -51,6 +53,7 @@ public String getId() { return id; } + @Nullable public Map getProperties() { return properties; } From e940845c6091fcf2feaf728e6e4e023006cf5af1 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 20 Feb 2019 16:40:26 +0800 Subject: [PATCH 0030/2639] Fix not correct mod installation --- .../java/org/jackhuang/hmcl/mod/ModManager.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java index 24694d524d..020cb12ba4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java @@ -85,13 +85,15 @@ public ModInfo getModInfo(File modFile) { public void refreshMods() throws IOException { modInfos.clear(); - for (Path subitem : Files.newDirectoryStream(getModsDirectory())) { - if (Files.isDirectory(subitem) && VersionNumber.isIntVersionNumber(FileUtils.getName(subitem))) { - // If the folder name is game version, forge will search mod in this subdirectory - for (Path subsubitem : Files.newDirectoryStream(subitem)) - addModInfo(subsubitem.toFile()); - } else { - addModInfo(subitem.toFile()); + if (Files.isDirectory(getModsDirectory())) { + for (Path subitem : Files.newDirectoryStream(getModsDirectory())) { + if (Files.isDirectory(subitem) && VersionNumber.isIntVersionNumber(FileUtils.getName(subitem))) { + // If the folder name is game version, forge will search mod in this subdirectory + for (Path subsubitem : Files.newDirectoryStream(subitem)) + addModInfo(subsubitem.toFile()); + } else { + addModInfo(subitem.toFile()); + } } } loaded = true; From 3ae826d9ca3dd88a3beea0e26a5cd6ebb44f95af Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 20 Feb 2019 20:07:11 +0800 Subject: [PATCH 0031/2639] Fix task.getLastException does not receive subtasks' value --- .../org/jackhuang/hmcl/task/TaskExecutor.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) 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 c8212ac34f..257c14e49c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -24,6 +24,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; /** @@ -64,7 +65,7 @@ public void setScheduler(Scheduler scheduler) { public TaskExecutor start() { taskListeners.forEach(TaskListener::onStart); workerQueue.add(scheduler.schedule(() -> { - boolean flag = executeTasks(Collections.singleton(firstTask)); + boolean flag = executeTasks(Collections.singleton(firstTask), new AtomicReference<>()); taskListeners.forEach(it -> it.onStop(flag, this)); })); return this; @@ -74,7 +75,7 @@ public boolean test() { taskListeners.forEach(TaskListener::onStart); AtomicBoolean flag = new AtomicBoolean(true); Future future = scheduler.schedule(() -> { - flag.set(executeTasks(Collections.singleton(firstTask))); + flag.set(executeTasks(Collections.singleton(firstTask), new AtomicReference<>())); taskListeners.forEach(it -> it.onStop(flag.get(), this)); }); workerQueue.add(future); @@ -100,7 +101,7 @@ public synchronized void cancel() { } } - private boolean executeTasks(Collection tasks) throws InterruptedException { + private boolean executeTasks(Collection tasks, AtomicReference exception) throws InterruptedException { if (tasks.isEmpty()) return true; @@ -128,6 +129,8 @@ private boolean executeTasks(Collection tasks) throws Interrupte } catch (InterruptedException e) { return false; } + + exception.set(tasks.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null)); return success.get() && !canceled; } @@ -160,9 +163,12 @@ private boolean executeTask(Task task) { } } - boolean doDependentsSucceeded = executeTasks(task.getDependents()); - if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) + AtomicReference dependentsException = new AtomicReference<>(); + boolean doDependentsSucceeded = executeTasks(task.getDependents(), dependentsException); + if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) { + task.setLastException(dependentsException.get()); throw new SilentException(); + } if (doDependentsSucceeded) task.setDependentsSucceeded(); @@ -187,9 +193,11 @@ private boolean executeTask(Task task) { variables.set(taskResult.getId(), taskResult.getResult()); } - boolean doDependenciesSucceeded = executeTasks(task.getDependencies()); + AtomicReference dependenciesException = new AtomicReference<>(); + boolean doDependenciesSucceeded = executeTasks(task.getDependencies(), dependenciesException); if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { Logging.LOG.severe("Subtasks failed for " + task.getName()); + task.setLastException(dependenciesException.get()); throw new SilentException(); } From e57180eb150d00c032134f22ffda1c7771d65e96 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 20 Feb 2019 20:07:43 +0800 Subject: [PATCH 0032/2639] remove lastException in task.variables --- .../ui/account/AddAuthlibInjectorServerPane.java | 3 +-- .../ui/download/VanillaInstallWizardProvider.java | 2 +- .../jackhuang/hmcl/ui/download/VersionsPage.java | 4 ++-- .../org/jackhuang/hmcl/ui/versions/ModListPage.java | 2 +- .../jackhuang/hmcl/ui/versions/WorldListPage.java | 2 +- .../org/jackhuang/hmcl/upgrade/UpdateHandler.java | 3 +-- .../jackhuang/hmcl/download/DefaultGameBuilder.java | 2 +- .../org/jackhuang/hmcl/task/FinalizedCallback.java | 2 +- .../java/org/jackhuang/hmcl/task/FinalizedTask.java | 8 ++++---- .../src/main/java/org/jackhuang/hmcl/task/Task.java | 13 ++++++------- .../java/org/jackhuang/hmcl/task/TaskExecutor.java | 3 --- .../java/org/jackhuang/hmcl/task/TaskResult.java | 4 ++-- .../org/jackhuang/hmcl/util/gson/Validation.java | 1 + 13 files changed, 22 insertions(+), 27 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 6c8d0bd5e2..68f2be8d81 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ private void onAddNext() { Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { + }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); @@ -118,7 +118,6 @@ private void onAddNext() { transitionHandler.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT.getAnimationProducer()); } else { - Exception exception = variables.get("lastException"); LOG.log(Level.WARNING, "Failed to resolve auth server: " + url, exception); lblCreationWarning.setText(resolveFetchExceptionMessage(exception)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 9a3e6bcbfb..087e8cae3b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ private Task finishVersionDownloadingAsync(Map settings) { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().finalized((a, b, c) -> profile.getRepository().refreshVersions()) .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); } 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 13b4d9c562..e7d64e8b77 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 @@ -128,7 +128,7 @@ private List loadVersions() { @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); @@ -147,7 +147,7 @@ public void refresh() { } }); } else { - LOG.log(Level.WARNING, "Failed to fetch versions list", (Throwable) variables.get("lastException")); + LOG.log(Level.WARNING, "Failed to fetch versions list", exception); Platform.runLater(() -> { transitionHandler.setContent(failedPane, ContainerAnimations.FADE.getAnimationProducer()); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 3b7a800019..904b9801ad 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -92,7 +92,7 @@ public void loadMods(ModManager modManager) { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded) -> { + }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 304eafaa95..b7592469e1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -52,7 +52,7 @@ public void loadVersion(Profile profile, String id) { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded) -> { + .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 55dde966fb..3e66cf84ed 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -121,8 +121,7 @@ public static void updateFrom(RemoteVersion version) { } } else { - Throwable e = task.getLastException(); - LOG.log(Level.WARNING, "Failed to update to " + version, e); + LOG.log(Level.WARNING, "Failed to update to " + version, executor.getLastException()); Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE)); } }); 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 5ed67f757e..19045d5ac8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -69,7 +69,7 @@ public Task buildAsync() { result = result.then(dependencyManager.installLibraryAsync(remoteVersion)); return result; - }).finalized((variables, isDependentsSucceeded) -> { + }).finalized((variables, isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java index 3de732d9c0..539b6f11d1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java @@ -20,5 +20,5 @@ import org.jackhuang.hmcl.util.AutoTypingMap; public interface FinalizedCallback { - void execute(AutoTypingMap variables, boolean isDependentsSucceeded) throws Exception; + void execute(AutoTypingMap variables, boolean isDependentsSucceeded, Exception exception) throws Exception; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java index 1a76914747..d0b6caef45 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java @@ -27,7 +27,7 @@ */ final class FinalizedTask extends Task { - private final Collection dependents; + private final Task pred; private final FinalizedCallback callback; private final Scheduler scheduler; @@ -38,7 +38,7 @@ final class FinalizedTask extends Task { * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. */ public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback, String name) { - this.dependents = Collections.singleton(pred); + this.pred = pred; this.scheduler = scheduler; this.callback = callback; @@ -53,7 +53,7 @@ public Scheduler getScheduler() { @Override public void execute() throws Exception { - callback.execute(getVariables(), isDependentsSucceeded()); + callback.execute(getVariables(), isDependentsSucceeded(), pred.getLastException()); if (!isDependentsSucceeded()) throw new SilentException(); @@ -61,7 +61,7 @@ public void execute() throws Exception { @Override public Collection getDependents() { - return dependents; + return Collections.singleton(pred); } @Override 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 3938dac5e9..631c8ae55a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -68,13 +68,13 @@ void setState(TaskState state) { this.state = state; } - private Throwable lastException = null; + private Exception lastException; - public Throwable getLastException() { + public Exception getLastException() { return lastException; } - void setLastException(Throwable e) { + void setLastException(Exception e) { lastException = e; } @@ -321,7 +321,7 @@ public final Task finalized(Scheduler scheduler, FinalizedCallback b) { } public final Task finalized(Scheduler scheduler, ExceptionalConsumer, T> success, ExceptionalConsumer failure) { - return finalized(scheduler, (variables, isDependentsSucceeded) -> { + return finalized(scheduler, (variables, isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { if (success != null) try { @@ -331,10 +331,9 @@ public final Task finalized(Scheduler if (failure != null) failure.accept(e); } - } - else { + } else { if (failure != null) - failure.accept(variables.get(TaskExecutor.LAST_EXCEPTION_ID)); + failure.accept(exception); } }); } 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 257c14e49c..68bda2a5de 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -234,7 +234,6 @@ private boolean executeTask(Task task) { } catch (Exception e) { task.setLastException(e); lastException = e; - variables.set(LAST_EXCEPTION_ID, e); if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); } @@ -279,6 +278,4 @@ public void run() { } } - - public static final String LAST_EXCEPTION_ID = "lastException"; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index e9d6fecf85..533fead550 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -61,7 +61,7 @@ public Task finalizedResult(Scheduler public Task finalizedResult(Scheduler scheduler, FinalizedCallback callback) { return new FinalizedTask(this, scheduler, - (variables, isDependentsSucceeded) -> callback.execute(getResult(), isDependentsSucceeded), + (variables, isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception), ReflectionHelper.getCaller().toString()); } @@ -98,6 +98,6 @@ public void execute() throws Exception { } public interface FinalizedCallback { - void execute(V result, boolean isDependentsSucceeded) throws Exception; + void execute(V result, boolean isDependentsSucceeded, Exception exception) throws Exception; } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java index b987f8a383..b51220da78 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java @@ -35,6 +35,7 @@ public interface Validation { * Throw an exception when values are malformed. * * @throws JsonParseException if fields are filled in wrong format or wrong type. + * @throws TolerableValidationException if we want to replace this object with null (i.e. the object does not fulfill the constraints). */ void validate() throws JsonParseException, TolerableValidationException; } From 608a531655268c5fc96b220298fc238be0931b78 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 20 Feb 2019 20:18:34 +0800 Subject: [PATCH 0033/2639] Remove AtomicReference --- .../org/jackhuang/hmcl/task/TaskExecutor.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) 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 68bda2a5de..074e1c1615 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -24,7 +24,6 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; /** @@ -65,7 +64,7 @@ public void setScheduler(Scheduler scheduler) { public TaskExecutor start() { taskListeners.forEach(TaskListener::onStart); workerQueue.add(scheduler.schedule(() -> { - boolean flag = executeTasks(Collections.singleton(firstTask), new AtomicReference<>()); + boolean flag = executeTasks(Collections.singleton(firstTask)); taskListeners.forEach(it -> it.onStop(flag, this)); })); return this; @@ -75,7 +74,7 @@ public boolean test() { taskListeners.forEach(TaskListener::onStart); AtomicBoolean flag = new AtomicBoolean(true); Future future = scheduler.schedule(() -> { - flag.set(executeTasks(Collections.singleton(firstTask), new AtomicReference<>())); + flag.set(executeTasks(Collections.singleton(firstTask))); taskListeners.forEach(it -> it.onStop(flag.get(), this)); }); workerQueue.add(future); @@ -101,7 +100,7 @@ public synchronized void cancel() { } } - private boolean executeTasks(Collection tasks, AtomicReference exception) throws InterruptedException { + private boolean executeTasks(Collection tasks) throws InterruptedException { if (tasks.isEmpty()) return true; @@ -129,8 +128,6 @@ private boolean executeTasks(Collection tasks, AtomicReference dependentsException = new AtomicReference<>(); - boolean doDependentsSucceeded = executeTasks(task.getDependents(), dependentsException); + Collection dependents = task.getDependents(); + boolean doDependentsSucceeded = executeTasks(dependents); + Exception dependentsException = dependents.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) { - task.setLastException(dependentsException.get()); + task.setLastException(dependentsException); throw new SilentException(); } @@ -193,11 +191,12 @@ private boolean executeTask(Task task) { variables.set(taskResult.getId(), taskResult.getResult()); } - AtomicReference dependenciesException = new AtomicReference<>(); - boolean doDependenciesSucceeded = executeTasks(task.getDependencies(), dependenciesException); + Collection dependencies = task.getDependencies(); + boolean doDependenciesSucceeded = executeTasks(dependencies); + Exception dependenciesException = dependencies.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { Logging.LOG.severe("Subtasks failed for " + task.getName()); - task.setLastException(dependenciesException.get()); + task.setLastException(dependenciesException); throw new SilentException(); } From 1bf2f175381371d2607290ad217555b02938f29d Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 18:38:43 +0800 Subject: [PATCH 0034/2639] Fix #533 --- .../org/jackhuang/hmcl/game/TexturesLoader.java | 17 ++++++++++++++--- .../jackhuang/hmcl/auth/yggdrasil/Texture.java | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index 028c73ec6d..26d957a771 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -17,7 +17,9 @@ */ package org.jackhuang.hmcl.game; +import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; +import static java.util.Objects.requireNonNull; import static org.jackhuang.hmcl.util.Lang.threadPool; import static org.jackhuang.hmcl.util.Logging.LOG; @@ -48,6 +50,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService; import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.javafx.MultiStepBinding; import javafx.beans.binding.Bindings; @@ -69,8 +72,8 @@ public static class LoadedTexture { private final Map metadata; public LoadedTexture(BufferedImage image, Map metadata) { - this.image = image; - this.metadata = metadata; + this.image = requireNonNull(image); + this.metadata = requireNonNull(metadata); } public BufferedImage getImage() { @@ -98,6 +101,10 @@ private static Path getTexturePath(Texture texture) { } public static LoadedTexture loadTexture(Texture texture) throws IOException { + if (StringUtils.isBlank(texture.getUrl())) { + throw new IOException("Texture url is empty"); + } + Path file = getTexturePath(texture); if (!Files.isRegularFile(file)) { // download it @@ -118,7 +125,11 @@ public static LoadedTexture loadTexture(Texture texture) throws IOException { try (InputStream in = Files.newInputStream(file)) { img = ImageIO.read(in); } - return new LoadedTexture(img, texture.getMetadata()); + Map metadata = texture.getMetadata(); + if (metadata == null) { + metadata = emptyMap(); + } + return new LoadedTexture(img, metadata); } // ==== diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/Texture.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/Texture.java index 54e10b9eba..3a0b7d46c3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/Texture.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/Texture.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.auth.yggdrasil; import org.jackhuang.hmcl.util.Immutable; +import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -36,10 +37,12 @@ public Texture(String url, Map metadata) { this.metadata = metadata; } + @Nullable public String getUrl() { return url; } + @Nullable public Map getMetadata() { return metadata; } From b396e0b2087d8294223720784d859a86b1db3d99 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 18:41:39 +0800 Subject: [PATCH 0035/2639] Fix compilation error --- .../main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 3e66cf84ed..c97f1cf4af 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -102,7 +102,7 @@ public static void updateFrom(RemoteVersion version) { Task task = new HMCLDownloadTask(version, downloaded); TaskExecutor executor = task.executor(); - Region dialog = Controllers.taskDialog(executor, i18n("message.downloading")); + Controllers.taskDialog(executor, i18n("message.downloading")); thread(() -> { boolean success = executor.test(); @@ -121,7 +121,8 @@ public static void updateFrom(RemoteVersion version) { } } else { - LOG.log(Level.WARNING, "Failed to update to " + version, executor.getLastException()); + Throwable e = executor.getLastException(); + LOG.log(Level.WARNING, "Failed to update to " + version, e); Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE)); } }); From 0f33981c96817a7d6c0c3d1f724245cc684cca68 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 23 Feb 2019 19:13:24 +0800 Subject: [PATCH 0036/2639] Fix #534 --- .../java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java index 3c87bd0538..9b6c1a27d9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java @@ -72,7 +72,7 @@ public void fire() { right.getChildren().add(btnRemove); root.setRight(right); - root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;"); + root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 12;"); JFXDepthManager.setDepth(root, 1); item.titleProperty().bind(skinnable.titleProperty()); item.subtitleProperty().bind(skinnable.subtitleProperty()); From 46d27a04a28bb96a7c52b457eefd016d604390f1 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 21:49:38 +0800 Subject: [PATCH 0037/2639] Fix auth server list in add account pane --- HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java | 1 + 1 file changed, 1 insertion(+) 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 c03fae6c8c..85a454c378 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -510,6 +510,7 @@ public static Callback, ListCell> jfxListCellFactory(Function public void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (!empty) { + setContentDisplay(ContentDisplay.GRAPHIC_ONLY); setGraphic(graphicBuilder.apply(item)); } } From bc9a9ffb726c5dfc0ff86b0616d2b31758b2f7fa Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 21:58:44 +0800 Subject: [PATCH 0038/2639] rewrite MultiStepBinding.asyncMap --- .../jackhuang/hmcl/game/TexturesLoader.java | 22 +++-- .../java/org/jackhuang/hmcl/util/Lang.java | 4 + .../hmcl/util/javafx/MultiStepBinding.java | 94 ++++++++++++------- 3 files changed, 79 insertions(+), 41 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index 26d957a771..ca42dc069e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -35,6 +35,7 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -163,20 +164,23 @@ public static ObjectBinding skinBinding(YggdrasilService service, return Optional.empty(); } }) - .flatMap(it -> Optional.ofNullable(it.get(TextureType.SKIN)))) + .flatMap(it -> Optional.ofNullable(it.get(TextureType.SKIN))) + .filter(it -> StringUtils.isNotBlank(it.getUrl()))) .asyncMap(it -> { if (it.isPresent()) { Texture texture = it.get(); - try { - return loadTexture(texture); - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to load texture " + texture.getUrl() + ", using fallback texture", e); - return getDefaultSkin(TextureModel.detectModelName(texture.getMetadata())); - } + return CompletableFuture.supplyAsync(() -> { + try { + return loadTexture(texture); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to load texture " + texture.getUrl() + ", using fallback texture", e); + return uuidFallback; + } + }, POOL); } else { - return uuidFallback; + return CompletableFuture.completedFuture(uuidFallback); } - }, uuidFallback, POOL); + }, uuidFallback); } // ==== diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index 195d7cf184..01e55f007e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -220,4 +220,8 @@ public static T apply(T t, Consumer consumer) { consumer.accept(t); return t; } + + public static void handleUncaughtException(Throwable e) { + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java index 7f6ce0cb07..56cc3f6c26 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java @@ -18,13 +18,13 @@ package org.jackhuang.hmcl.util.javafx; import static java.util.Objects.requireNonNull; +import static org.jackhuang.hmcl.util.Lang.handleUncaughtException; import java.util.Objects; -import java.util.concurrent.Executor; +import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.function.Supplier; -import org.jackhuang.hmcl.util.InvocationDispatcher; import javafx.application.Platform; import javafx.beans.binding.ObjectBinding; @@ -58,8 +58,8 @@ public MultiStepBinding flatMap(Function(map(mapper), nullAlternative); } - public MultiStepBinding asyncMap(Function mapper, V initial, Executor executor) { - return new AsyncMappedBinding<>(this, mapper, executor, initial); + public MultiStepBinding asyncMap(Function> mapper, V initial) { + return new AsyncMappedBinding<>(this, mapper, initial); } private static class SimpleBinding extends MultiStepBinding { @@ -79,8 +79,8 @@ public MultiStepBinding map(Function mapper) { } @Override - public MultiStepBinding asyncMap(Function mapper, V initial, Executor executor) { - return new AsyncMappedBinding<>(predecessor, mapper, executor, initial); + public MultiStepBinding asyncMap(Function> mapper, V initial) { + return new AsyncMappedBinding<>(predecessor, mapper, initial); } } @@ -136,49 +136,79 @@ protected U computeValue() { private static class AsyncMappedBinding extends MultiStepBinding { - private final InvocationDispatcher dispatcher; - private boolean initialized = false; private T prev; private U value; - public AsyncMappedBinding(ObservableValue predecessor, Function mapper, Executor executor, U initial) { + private final Function> mapper; + private T computingPrev; + private boolean computing = false; + + public AsyncMappedBinding(ObservableValue predecessor, Function> mapper, U initial) { super(predecessor); this.value = initial; + this.mapper = mapper; + } - dispatcher = InvocationDispatcher.runOn(executor, arg -> { - synchronized (this) { - if (initialized && Objects.equals(arg, prev)) { - return; - } + private void tryUpdateValue(T currentPrev) { + synchronized (this) { + if ((initialized && Objects.equals(prev, currentPrev)) + || isComputing(currentPrev)) { + return; } - U newValue = mapper.apply(arg); - synchronized (this) { - prev = arg; - value = newValue; - initialized = true; + computing = true; + computingPrev = currentPrev; + } + + CompletableFuture task; + try { + task = requireNonNull(mapper.apply(currentPrev)); + } catch (Throwable e) { + valueUpdateFailed(currentPrev); + throw e; + } + + task.handle((result, e) -> { + if (e == null) { + valueUpdate(currentPrev, result); + Platform.runLater(this::invalidate); + } else { + handleUncaughtException(e); + valueUpdateFailed(currentPrev); } - Platform.runLater(this::invalidate); + return null; }); } - // called on FX thread, this method is serial - @Override - protected U computeValue() { - T currentPrev = predecessor.getValue(); - U value; - boolean updateNeeded = false; + private void valueUpdate(T currentPrev, U computed) { synchronized (this) { - value = this.value; - if (!initialized || !Objects.equals(currentPrev, prev)) { - updateNeeded = true; + if (isComputing(currentPrev)) { + computing = false; + computingPrev = null; + prev = currentPrev; + value = computed; + initialized = true; } } - if (updateNeeded) { - dispatcher.accept(currentPrev); + } + + private void valueUpdateFailed(T currentPrev) { + synchronized (this) { + if (isComputing(currentPrev)) { + computing = false; + computingPrev = null; + } } - return value; } + private boolean isComputing(T prev) { + return computing && Objects.equals(prev, computingPrev); + } + + @Override + protected U computeValue() { + tryUpdateValue(predecessor.getValue()); + return value; + } } } From 7c89fac1e90ad20c4f2511d1bf0fd9d64b6ccbe9 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 22:14:29 +0800 Subject: [PATCH 0039/2639] Rename MultiStepBinding->BindingMapping --- .../jackhuang/hmcl/game/TexturesLoader.java | 6 ++-- .../org/jackhuang/hmcl/setting/Theme.java | 4 ++- .../org/jackhuang/hmcl/ui/Controllers.java | 4 +-- .../hmcl/ui/account/AccountListItemSkin.java | 3 +- .../hmcl/ui/account/AddAccountPane.java | 4 +-- .../hmcl/ui/construct/FontComboBox.java | 4 +-- ...tiStepBinding.java => BindingMapping.java} | 36 ++++++++++++------- .../hmcl/util/javafx/ExtendedProperties.java | 4 +-- 8 files changed, 39 insertions(+), 26 deletions(-) rename HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/{MultiStepBinding.java => BindingMapping.java} (80%) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index ca42dc069e..19fb1273d3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -52,7 +52,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.javafx.MultiStepBinding; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; @@ -154,7 +154,7 @@ public static LoadedTexture getDefaultSkin(TextureModel model) { public static ObjectBinding skinBinding(YggdrasilService service, UUID uuid) { LoadedTexture uuidFallback = getDefaultSkin(TextureModel.detectUUID(uuid)); - return MultiStepBinding.of(service.getProfileRepository().binding(uuid)) + return BindingMapping.of(service.getProfileRepository().binding(uuid)) .map(profile -> profile .flatMap(it -> { try { @@ -204,7 +204,7 @@ public static BufferedImage toAvatar(BufferedImage skin, int size) { } public static ObjectBinding fxAvatarBinding(YggdrasilService service, UUID uuid, int size) { - return MultiStepBinding.of(skinBinding(service, uuid)) + return BindingMapping.of(skinBinding(service, uuid)) .map(it -> toAvatar(it.image, size)) .map(img -> SwingFXUtils.toFXImage(img, null)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java index 85db751780..9d592ca80e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java @@ -27,6 +27,7 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import java.io.File; import java.io.IOException; @@ -132,7 +133,8 @@ public static String getColorDisplayName(Color c) { } public static ObjectBinding foregroundFillBinding() { - return Bindings.createObjectBinding(() -> config().getTheme().getForegroundColor(), config().themeProperty()); + return BindingMapping.of(config().themeProperty()) + .map(Theme::getForegroundColor); } public static ObjectBinding blackFillBinding() { 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 8a2de0b6fe..6439af6fa6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -45,7 +45,7 @@ import org.jackhuang.hmcl.util.FutureCallback; import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.javafx.MultiStepBinding; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.versioning.VersionNumber; @@ -158,7 +158,7 @@ public static MainPage getMainPage() { }); mainPage.showUpdateProperty().bind(UpdateChecker.outdatedProperty()); mainPage.latestVersionProperty().bind( - MultiStepBinding.of(UpdateChecker.latestVersionProperty()) + BindingMapping.of(UpdateChecker.latestVersionProperty()) .map(version -> version == null ? "" : i18n("update.bubble.title", version.getVersion()))); Profiles.registerVersionsListener(profile -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index c986c317b0..8614697779 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -35,6 +35,7 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -75,7 +76,7 @@ public void fire() { if (skinnable.getAccount() instanceof AuthlibInjectorAccount) { Tooltip tooltip = new Tooltip(); AuthlibInjectorServer server = ((AuthlibInjectorAccount) skinnable.getAccount()).getServer(); - tooltip.textProperty().bind(Bindings.createStringBinding(server::toString, server)); + tooltip.textProperty().bind(BindingMapping.of(server, AuthlibInjectorServer::toString)); FXUtils.installSlowTooltip(subtitle, tooltip); } VBox item = new VBox(title, subtitle); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index cbe283d8f4..06744aa4c5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -47,7 +47,7 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.*; -import org.jackhuang.hmcl.util.javafx.MultiStepBinding; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import java.util.ArrayList; import java.util.List; @@ -126,7 +126,7 @@ public AddAccountPane() { cboServers.getSelectionModel().selectedItemProperty(), cboServers.visibleProperty())); // authlib-injector links - links.bind(MultiStepBinding.of(cboServers.getSelectionModel().selectedItemProperty()) + links.bind(BindingMapping.of(cboServers.getSelectionModel().selectedItemProperty()) .map(AddAccountPane::createHyperlinks) .map(FXCollections::observableList)); Bindings.bindContent(linksContainer.getChildren(), links); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java index abb1d10f36..3a87d29905 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java @@ -21,7 +21,7 @@ import static javafx.collections.FXCollections.observableList; import static javafx.collections.FXCollections.singletonObservableList; -import org.jackhuang.hmcl.util.javafx.MultiStepBinding; +import org.jackhuang.hmcl.util.javafx.BindingMapping; import com.jfoenix.controls.JFXComboBox; import com.jfoenix.controls.JFXListCell; @@ -49,7 +49,7 @@ public void updateItem(String item, boolean empty) { } }); - itemsProperty().bind(MultiStepBinding.of(valueProperty()) + itemsProperty().bind(BindingMapping.of(valueProperty()) .map(value -> value == null ? emptyObservableList() : singletonObservableList(value))); setOnMouseClicked(e -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/BindingMapping.java similarity index 80% rename from HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java rename to HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/BindingMapping.java index 56cc3f6c26..7fe1441a0d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/MultiStepBinding.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/BindingMapping.java @@ -27,42 +27,52 @@ import javafx.application.Platform; +import javafx.beans.Observable; +import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.value.ObservableValue; /** * @author yushijinhun */ -public abstract class MultiStepBinding extends ObjectBinding { +public abstract class BindingMapping extends ObjectBinding { - public static MultiStepBinding of(ObservableValue property) { + @SuppressWarnings("unchecked") + public static BindingMapping of(ObservableValue property) { + if (property instanceof BindingMapping) { + return (BindingMapping) property; + } return new SimpleBinding<>(property); } + public static BindingMapping of(S watched, Function mapper) { + return of(Bindings.createObjectBinding(() -> mapper.apply(watched), watched)); + } + protected final ObservableValue predecessor; - public MultiStepBinding(ObservableValue predecessor) { + public BindingMapping(ObservableValue predecessor) { this.predecessor = requireNonNull(predecessor); bind(predecessor); } - public MultiStepBinding map(Function mapper) { + public BindingMapping map(Function mapper) { return new MappedBinding<>(this, mapper); } - public MultiStepBinding flatMap(Function> mapper) { + public BindingMapping flatMap(Function> mapper) { return flatMap(mapper, null); } - public MultiStepBinding flatMap(Function> mapper, Supplier nullAlternative) { + public BindingMapping flatMap(Function> mapper, Supplier nullAlternative) { return new FlatMappedBinding<>(map(mapper), nullAlternative); } - public MultiStepBinding asyncMap(Function> mapper, V initial) { + public BindingMapping asyncMap(Function> mapper, V initial) { return new AsyncMappedBinding<>(this, mapper, initial); } - private static class SimpleBinding extends MultiStepBinding { + private static class SimpleBinding extends BindingMapping { public SimpleBinding(ObservableValue predecessor) { super(predecessor); @@ -74,17 +84,17 @@ protected T computeValue() { } @Override - public MultiStepBinding map(Function mapper) { + public BindingMapping map(Function mapper) { return new MappedBinding<>(predecessor, mapper); } @Override - public MultiStepBinding asyncMap(Function> mapper, V initial) { + public BindingMapping asyncMap(Function> mapper, V initial) { return new AsyncMappedBinding<>(predecessor, mapper, initial); } } - private static class MappedBinding extends MultiStepBinding { + private static class MappedBinding extends BindingMapping { private final Function mapper; @@ -99,7 +109,7 @@ protected U computeValue() { } } - private static class FlatMappedBinding, U> extends MultiStepBinding { + private static class FlatMappedBinding, U> extends BindingMapping { private final Supplier nullAlternative; private T lastObservable = null; @@ -134,7 +144,7 @@ protected U computeValue() { } } - private static class AsyncMappedBinding extends MultiStepBinding { + private static class AsyncMappedBinding extends BindingMapping { private boolean initialized = false; private T prev; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java index 1c10b07a56..e908c3b305 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java @@ -53,7 +53,7 @@ public static ObjectProperty selectedItemPropertyFor(ComboBox comboBox private static ObjectProperty createPropertyForSelectionModel(Object bean, Property> modelProperty) { return new ReadWriteComposedProperty<>(bean, "extra.selectedItem", - MultiStepBinding.of(modelProperty) + BindingMapping.of(modelProperty) .flatMap(SelectionModel::selectedItemProperty), obj -> modelProperty.getValue().select(obj)); } @@ -107,7 +107,7 @@ private static ObjectProperty createMappedPropertyForToggleGroup(ToggleGr }; ReadWriteComposedProperty property = new ReadWriteComposedProperty<>(toggleGroup, "extra.selectedItem", - MultiStepBinding.of(selectedTogglePropertyFor(toggleGroup)) + BindingMapping.of(selectedTogglePropertyFor(toggleGroup)) .map(mapper), itemSelector); From e5587418c7e6363243832b83345250658684be0c Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 22:36:38 +0800 Subject: [PATCH 0040/2639] Remove SafeIntStringConverter --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 3 +- .../hmcl/ui/SafeIntStringConverter.java | 43 ------------------- 2 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/SafeIntStringConverter.java 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 85a454c378..f555d7f836 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -48,6 +48,7 @@ import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.javafx.ExtendedProperties; +import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.io.File; @@ -331,7 +332,7 @@ public static void openLink(String link) { } public static void bindInt(JFXTextField textField, Property property) { - textField.textProperty().bindBidirectional(property, SafeIntStringConverter.INSTANCE); + textField.textProperty().bindBidirectional(property, SafeStringConverter.fromInteger()); } public static void unbindInt(JFXTextField textField, Property property) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SafeIntStringConverter.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SafeIntStringConverter.java deleted file mode 100644 index dfe9af4d60..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SafeIntStringConverter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.ui; - -import javafx.util.StringConverter; -import org.jackhuang.hmcl.util.Lang; - -import java.util.Optional; - -/** - * @author huangyuhui - */ -public final class SafeIntStringConverter extends StringConverter { - public static final SafeIntStringConverter INSTANCE = new SafeIntStringConverter(); - - private SafeIntStringConverter() { - } - - @Override - public Number fromString(String string) { - return Optional.ofNullable(string).map(Lang::toIntOrNull).orElse(null); - } - - @Override - public String toString(Number object) { - return Optional.ofNullable(object).map(Object::toString).orElse(""); - } -} From fff7abc2ac1fd1bef06052fb9eec5c5c415b1b81 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 23 Feb 2019 21:16:43 +0800 Subject: [PATCH 0041/2639] finalized no longer passes AutoTypingMap as callback parameter --- .../jackhuang/hmcl/game/ModpackHelper.java | 6 ++--- .../hmcl/ui/account/AccountLoginPane.java | 2 +- .../hmcl/ui/account/AddAccountPane.java | 2 +- .../account/AddAuthlibInjectorServerPane.java | 2 +- .../hmcl/ui/download/ModpackPage.java | 2 +- .../VanillaInstallWizardProvider.java | 2 +- .../hmcl/ui/download/VersionsPage.java | 2 +- .../hmcl/ui/versions/ModListPage.java | 2 +- .../hmcl/ui/versions/WorldListPage.java | 7 +++--- .../hmcl/download/DefaultGameBuilder.java | 2 +- .../hmcl/task/FinalizedCallback.java | 24 ------------------- .../jackhuang/hmcl/task/FinalizedTask.java | 2 +- .../java/org/jackhuang/hmcl/task/Task.java | 11 ++++++--- .../org/jackhuang/hmcl/task/TaskResult.java | 10 ++++---- 14 files changed, 27 insertions(+), 49 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index eb7be914d2..c4bfdac61d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -110,13 +110,13 @@ public static Task getInstallTask(Profile profile, File zipFile, String name, Mo if (modpack.getManifest() instanceof CurseManifest) return new CurseInstallTask(profile.getDependency(), zipFile, modpack, ((CurseManifest) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure); + .finalized(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof HMCLModpackManifest) return new HMCLModpackInstallTask(profile, zipFile, modpack, name) - .finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure); + .finalized(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure) + .finalized(Schedulers.defaultScheduler(), success, failure) .then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); else throw new IllegalStateException("Unrecognized modpack: " + modpack); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java index 4e739e05ee..01b6ae5523 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java @@ -62,7 +62,7 @@ private void onAccept() { progressBar.setVisible(true); lblCreationWarning.setText(""); Task.ofResult(() -> oldAccount.logInWithPassword(password)) - .finalizedResult(Schedulers.javafx(), authInfo -> { + .finalized(Schedulers.javafx(), authInfo -> { success.accept(authInfo); fireEvent(new DialogCloseEvent()); progressBar.setVisible(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 06744aa4c5..32c76b49f1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -196,7 +196,7 @@ private void onCreationAccept() { Object additionalData = getAuthAdditionalData(); Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData)) - .finalizedResult(Schedulers.javafx(), account -> { + .finalized(Schedulers.javafx(), account -> { int oldIndex = Accounts.getAccounts().indexOf(account); if (oldIndex == -1) { Accounts.getAccounts().add(account); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 68f2be8d81..85ec12ba13 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ private void onAddNext() { Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded, exception) -> { + }).finalized(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); 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 4efc6f38b9..c5094bb250 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 @@ -111,7 +111,7 @@ public ModpackPage(WizardController controller) { spinnerPane.showSpinner(); Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath())) .thenResult(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) - .finalizedResult(Schedulers.javafx(), manifest -> { + .finalized(Schedulers.javafx(), manifest -> { spinnerPane.hideSpinner(); controller.getSettings().put(MODPACK_MANIFEST, manifest); lblName.setText(manifest.getName()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 087e8cae3b..9a3e6bcbfb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ private Task finishVersionDownloadingAsync(Map settings) { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().finalized((a, b, c) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()) .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); } 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 e7d64e8b77..1787606c33 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 @@ -128,7 +128,7 @@ private List loadVersions() { @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded, exception) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 904b9801ad..97f7e1b440 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -92,7 +92,7 @@ public void loadMods(ModManager modManager) { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { + }).finalized(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index b7592469e1..195da3bd74 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -29,7 +29,6 @@ import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; -import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Path; import java.util.List; @@ -52,7 +51,7 @@ public void loadVersion(Profile profile, String id) { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { + .finalized(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); @@ -74,10 +73,10 @@ private void installWorld(File zipFile) { // Only accept one world file because user is required to confirm the new world name // Or too many input dialogs are popped. Task.ofResult(() -> new World(zipFile.toPath())) - .finalizedResult(Schedulers.javafx(), world -> { + .finalized(Schedulers.javafx(), world -> { Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { Task.of(() -> world.install(savesDir, name)) - .finalized(Schedulers.javafx(), var -> { + .finalized(Schedulers.javafx(), () -> { itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); resolve.run(); }, e -> { 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 19045d5ac8..111d5f8c7b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -69,7 +69,7 @@ public Task buildAsync() { result = result.then(dependencyManager.installLibraryAsync(remoteVersion)); return result; - }).finalized((variables, isDependentsSucceeded, exception) -> { + }).finalized((isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java deleted file mode 100644 index 539b6f11d1..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.AutoTypingMap; - -public interface FinalizedCallback { - void execute(AutoTypingMap variables, boolean isDependentsSucceeded, Exception exception) throws Exception; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java index d0b6caef45..fd37f20e7b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java @@ -53,7 +53,7 @@ public Scheduler getScheduler() { @Override public void execute() throws Exception { - callback.execute(getVariables(), isDependentsSucceeded(), pred.getLastException()); + callback.execute(isDependentsSucceeded(), pred.getLastException()); if (!isDependentsSucceeded()) throw new SilentException(); 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 631c8ae55a..b719b0a67f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -320,12 +320,13 @@ public final Task finalized(Scheduler scheduler, FinalizedCallback b) { return new FinalizedTask(this, scheduler, b, ReflectionHelper.getCaller().toString()); } - public final Task finalized(Scheduler scheduler, ExceptionalConsumer, T> success, ExceptionalConsumer failure) { - return finalized(scheduler, (variables, isDependentsSucceeded, exception) -> { + // T, K here is necessary, or javac cannot infer type of failure + public final Task finalized(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { + return finalized(scheduler, (isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { if (success != null) try { - success.accept(variables); + success.run(); } catch (Exception e) { Logging.LOG.log(Level.WARNING, "Failed to execute " + success, e); if (failure != null) @@ -421,4 +422,8 @@ public enum TaskState { SUCCEEDED, FAILED } + + public interface FinalizedCallback { + void execute(boolean isDependentsSucceeded, Exception exception) throws Exception; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index 533fead550..46f2ecc556 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -55,14 +55,12 @@ public TaskResult thenResult(String id, Scheduler sc return new Subtask<>(id, scheduler, task); } - public Task finalizedResult(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { - return finalized(scheduler, variables -> success.accept(getResult()), failure); + public Task finalized(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { + return finalized(scheduler, () -> success.accept(getResult()), failure); } - public Task finalizedResult(Scheduler scheduler, FinalizedCallback callback) { - return new FinalizedTask(this, scheduler, - (variables, isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception), - ReflectionHelper.getCaller().toString()); + public Task finalized(Scheduler scheduler, FinalizedCallback callback) { + return finalized(scheduler, ((isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception))); } private class Subtask extends TaskResult { From a388450f941c088352c69400f13daeb2eb4204be Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 23 Feb 2019 22:44:52 +0800 Subject: [PATCH 0042/2639] Remove AutoTypingMap --- .../jackhuang/hmcl/game/LauncherHelper.java | 59 +++++----- .../jackhuang/hmcl/ui/LeftPaneController.java | 3 +- .../ui/download/InstallerWizardProvider.java | 9 +- .../hmcl/ui/versions/InstallerListPage.java | 2 +- .../hmcl/ui/versions/ModListPage.java | 7 +- .../hmcl/ui/versions/VersionSettingsPage.java | 13 +-- .../download/DefaultDependencyManager.java | 34 +++--- .../hmcl/download/DefaultGameBuilder.java | 26 +++-- .../jackhuang/hmcl/download/MaintainTask.java | 13 --- .../jackhuang/hmcl/download/VersionList.java | 4 +- .../hmcl/download/forge/ForgeInstallTask.java | 5 - .../download/forge/ForgeNewInstallTask.java | 5 - .../download/forge/ForgeOldInstallTask.java | 5 - .../download/game/LibrariesUniqueTask.java | 11 -- .../game/VersionJsonDownloadTask.java | 7 +- .../download/game/VersionJsonSaveTask.java | 5 +- .../liteloader/LiteLoaderInstallTask.java | 6 - .../optifine/OptiFineInstallTask.java | 5 - .../hmcl/mod/MultiMCModpackInstallTask.java | 2 +- .../org/jackhuang/hmcl/task/CoupleTask.java | 34 +++--- .../jackhuang/hmcl/task/FinalizedTask.java | 3 +- .../java/org/jackhuang/hmcl/task/GetTask.java | 5 - .../org/jackhuang/hmcl/task/SimpleTask.java | 13 +-- .../jackhuang/hmcl/task/SimpleTaskResult.java | 28 +++-- .../java/org/jackhuang/hmcl/task/Task.java | 105 ++++++++---------- .../org/jackhuang/hmcl/task/TaskCallable.java | 52 --------- .../org/jackhuang/hmcl/task/TaskExecutor.java | 14 --- .../org/jackhuang/hmcl/task/TaskResult.java | 67 ++++++++--- .../jackhuang/hmcl/util/ReflectionHelper.java | 15 ++- 29 files changed, 230 insertions(+), 327 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskCallable.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 de641b771f..b5d17988e0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -122,14 +122,14 @@ private void launch0() { Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) - .then(variables -> { + .then(() -> { if (setting.isNotCheckGame()) return null; else return dependencyManager.checkGameCompletionAsync(version); }) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS))) - .then(var -> { + .then(() -> { try { ModpackConfiguration configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion)); if ("Curse".equals(configuration.getType())) @@ -141,44 +141,42 @@ private void launch0() { } }) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) - .then(Task.of(i18n("account.methods"), variables -> { + .thenTaskResult(() -> Task.ofResult(i18n("account.methods"), () -> { try { - variables.set("account", account.logIn()); + return account.logIn(); } catch (CredentialExpiredException e) { LOG.info("Credential has expired: " + e); - variables.set("account", DialogController.logIn(account)); + return DialogController.logIn(account); } catch (AuthenticationException e) { LOG.warning("Authentication failed, try playing offline: " + e); - variables.set("account", - account.playOffline().orElseThrow(() -> e)); + return account.playOffline().orElseThrow(() -> e); } })) - .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LAUNCHING))) - .then(Task.of(variables -> { - variables.set("launcher", new HMCLGameLauncher( - repository, - selectedVersion, - variables.get("account"), - setting.toLaunchOptions(profile.getGameDir()), - launcherVisibility == LauncherVisibility.CLOSE - ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. - : new HMCLProcessListener(variables.get("account"), setting, gameVersion.isPresent()) - )); - })) - .then(variables -> { - DefaultLauncher launcher = variables.get("launcher"); + .thenResult(Schedulers.javafx(), authInfo -> { + emitStatus(LoadingState.LAUNCHING); + return authInfo; + }) + .thenResult(authInfo -> new HMCLGameLauncher( + repository, + selectedVersion, + authInfo, + setting.toLaunchOptions(profile.getGameDir()), + launcherVisibility == LauncherVisibility.CLOSE + ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. + : new HMCLProcessListener(authInfo, setting, gameVersion.isPresent()) + )) + .thenTaskResult(launcher -> { // launcher is prev task's result if (scriptFile == null) { return new LaunchTask<>(launcher::launch).setName(i18n("version.launch")); } else { - return new LaunchTask<>(() -> { + return new LaunchTask(() -> { launcher.makeLaunchScript(scriptFile); return null; }).setName(i18n("version.launch_script")); } }) - .then(Task.of(variables -> { + .thenVoid(process -> { // process is LaunchTask's result if (scriptFile == null) { - ManagedProcess process = variables.get(LaunchTask.LAUNCH_ID); PROCESSES.add(process); if (launcherVisibility == LauncherVisibility.CLOSE) Launcher.stopApplication(); @@ -187,13 +185,13 @@ private void launch0() { process.stop(); it.fireEvent(new DialogCloseEvent()); }); - } else + } else { Platform.runLater(() -> { launchingStepsPane.fireEvent(new DialogCloseEvent()); Controllers.dialog(i18n("version.launch_script.success", scriptFile.getAbsolutePath())); }); - - })) + } + }) .executor(); launchingStepsPane.setExecutor(executor, false); @@ -429,13 +427,6 @@ public LaunchTask(ExceptionalSupplier supplier) { public void execute() throws Exception { setResult(supplier.get()); } - - @Override - public String getId() { - return LAUNCH_ID; - } - - static final String LAUNCH_ID = "launch"; } /** 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 bda00a0798..0479f27d03 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -121,13 +121,12 @@ private void onRefreshedVersions(HMCLGameRepository repository) { if (modpackFile.exists()) { Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) .thenResult(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) - .thenResult(modpack -> { + .thenVoid(modpack -> { AtomicReference region = new AtomicReference<>(); TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) .with(Task.of(Schedulers.javafx(), this::checkAccount)).executor(); region.set(Controllers.taskDialog(executor, i18n("modpack.installing"))); executor.start(); - return null; }).start(); } } 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 87f1360f5c..a38ad5f806 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 @@ -27,6 +27,7 @@ import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.wizard.WizardController; @@ -89,16 +90,16 @@ public Object finish(Map settings) { settings.put("success_message", i18n("install.success")); settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next)); - Task ret = Task.ofResult("version", () -> version); + TaskResult ret = Task.ofResult(() -> version); if (settings.containsKey("forge")) - ret = ret.then(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); + ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); if (settings.containsKey("liteloader")) - ret = ret.then(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); + ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); if (settings.containsKey("optifine")) - ret = ret.then(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); + ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); return ret.then(profile.getRepository().refreshVersionsAsync()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index 2b45437a40..020ff62de0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -54,7 +54,7 @@ public void loadVersion(Profile profile, String versionId) { LinkedList newList = new LinkedList<>(version.getLibraries()); newList.remove(library); new MaintainTask(version.setLibraries(newList)) - .then(variables -> new VersionJsonSaveTask(profile.getRepository(), variables.get(MaintainTask.ID))) + .then(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion)) .with(profile.getRepository().refreshVersionsAsync()) .with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))) .start(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 97f7e1b440..c420c5d5d7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -36,7 +36,6 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; -import org.jackhuang.hmcl.ui.ListPage; import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; @@ -86,7 +85,7 @@ public void loadVersion(Profile profile, String id) { public void loadMods(ModManager modManager) { this.modManager = modManager; - Task.ofResult("list", variables -> { + Task.ofResult(() -> { synchronized (ModListPage.this) { JFXUtilities.runInFX(() -> loadingProperty().set(true)); modManager.refreshMods(); @@ -112,7 +111,7 @@ public void add() { List succeeded = new LinkedList<>(); List failed = new LinkedList<>(); if (res == null) return; - Task.of(variables -> { + Task.of(() -> { for (File file : res) { try { modManager.addMod(file); @@ -124,7 +123,7 @@ public void add() { // Actually addMod will not throw exceptions because FileChooser has already filtered files. } } - }).with(Task.of(Schedulers.javafx(), variables -> { + }).with(Task.of(Schedulers.javafx(), () -> { List prompt = new LinkedList<>(); if (!succeeded.isEmpty()) prompt.add(i18n("mods.add.success", String.join(", ", succeeded))); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index b5b0b45e7d..971caed190 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -57,7 +57,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import java.util.List; +import java.util.Optional; import java.util.logging.Level; import java.util.stream.Collectors; @@ -113,14 +113,13 @@ private void initialize() { FXUtils.smoothScrolling(scroll); - Task.ofResult(JavaVersion::getJavas).thenResult(Schedulers.javafx(), list -> { + Task.ofResult(JavaVersion::getJavas).thenVoid(Schedulers.javafx(), list -> { javaItem.loadChildren(list.stream() .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) .collect(Collectors.toList())); javaItemsLoaded = true; initializeSelectedJava(); - return null; }).start(); javaItem.setSelectedData(null); @@ -268,10 +267,10 @@ private void initializeSelectedJava() { } private void initJavaSubtitle(VersionSetting versionSetting) { - Task.of(variables -> variables.set("java", versionSetting.getJavaVersion())) - .subscribe(Task.of(Schedulers.javafx(), - variables -> javaItem.setSubtitle(variables.getOptional("java") - .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Directory")))); + Task.ofResult(versionSetting::getJavaVersion) + .thenVoid(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) + .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Directory"))) + .start(); } @FXML diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index d121b4b33a..c094c719c0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -28,7 +28,7 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.AutoTypingMap; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.function.ExceptionalFunction; /** @@ -71,7 +71,7 @@ public GameBuilder gameBuilder() { @Override public Task checkGameCompletionAsync(Version version) { return new ParallelTask( - Task.ofThen(var -> { + Task.ofThen(() -> { if (!repository.getVersionJar(version).exists()) return new GameDownloadTask(this, null, version); else @@ -88,36 +88,32 @@ public Task checkLibraryCompletionAsync(Version version) { } @Override - public Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { + public TaskResult installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); return versionList.loadAsync(gameVersion, getDownloadProvider()) - .then(variables -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) + .thenTaskResult(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) .orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion)))); } @Override - public Task installLibraryAsync(Version version, RemoteVersion libraryVersion) { + public TaskResult installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) { + TaskResult task; if (libraryVersion instanceof ForgeRemoteVersion) - return new ForgeInstallTask(this, version, (ForgeRemoteVersion) libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + task = new ForgeInstallTask(this, oldVersion, (ForgeRemoteVersion) libraryVersion); else if (libraryVersion instanceof LiteLoaderRemoteVersion) - return new LiteLoaderInstallTask(this, version, (LiteLoaderRemoteVersion) libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + task = new LiteLoaderInstallTask(this, oldVersion, (LiteLoaderRemoteVersion) libraryVersion); else if (libraryVersion instanceof OptiFineRemoteVersion) - return new OptiFineInstallTask(this, version, (OptiFineRemoteVersion) libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + task = new OptiFineInstallTask(this, oldVersion, (OptiFineRemoteVersion) libraryVersion); else throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized."); + return task + .thenTaskResult(LibrariesUniqueTask::new) + .thenTaskResult(MaintainTask::new) + .thenTaskResult(newVersion -> new VersionJsonSaveTask(repository, newVersion)); } - public ExceptionalFunction, Task, ?> installLibraryAsync(RemoteVersion libraryVersion) { - return var -> installLibraryAsync(var.get("version"), libraryVersion); + public ExceptionalFunction, ?> installLibraryAsync(RemoteVersion libraryVersion) { + return version -> installLibraryAsync(version, libraryVersion); } } 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 111d5f8c7b..885517422e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -21,6 +21,7 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.AutoTypingMap; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -49,34 +50,35 @@ public DownloadProvider getDownloadProvider() { @Override public Task buildAsync() { - return new VersionJsonDownloadTask(gameVersion, dependencyManager).then(variables -> { - Version version = JsonUtils.GSON.fromJson(variables.get(VersionJsonDownloadTask.ID), Version.class); - version = version.setId(name).setJar(null); - variables.set("version", version); - Task result = downloadGameAsync(gameVersion, version).then(new ParallelTask( + return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenTaskResult(rawJson -> { + Version original = JsonUtils.GSON.fromJson(rawJson, Version.class); + Version version = original.setId(name).setJar(null); + Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask( new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY), new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. + TaskResult libraryTask = vanillaTask.thenResult(() -> version); + if (toolVersions.containsKey("forge")) - result = result.then(libraryTaskHelper(gameVersion, "forge")); + libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "forge")); if (toolVersions.containsKey("liteloader")) - result = result.then(libraryTaskHelper(gameVersion, "liteloader")); + libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "liteloader")); if (toolVersions.containsKey("optifine")) - result = result.then(libraryTaskHelper(gameVersion, "optifine")); + libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "optifine")); for (RemoteVersion remoteVersion : remoteVersions) - result = result.then(dependencyManager.installLibraryAsync(remoteVersion)); + libraryTask = libraryTask.thenTaskResult(dependencyManager.installLibraryAsync(remoteVersion)); - return result; + return libraryTask; }).finalized((isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); } - private ExceptionalFunction, Task, ?> libraryTaskHelper(String gameVersion, String libraryId) { - return variables -> dependencyManager.installLibraryAsync(gameVersion, variables.get("version"), libraryId, toolVersions.get(libraryId)); + private ExceptionalFunction, ?> libraryTaskHelper(String gameVersion, String libraryId) { + return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, toolVersions.get(libraryId)); } protected Task downloadGameAsync(String gameVersion, Version version) { 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 9199986659..c0a58dcbce 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -23,15 +23,9 @@ public class MaintainTask extends TaskResult { private final Version version; - private final String id; public MaintainTask(Version version) { - this(version, ID); - } - - public MaintainTask(Version version, String id) { this.version = version; - this.id = id; } @Override @@ -76,11 +70,4 @@ private static Version maintainGameWithLaunchWrapper(Version version) { return builder.build(); } - - @Override - public String getId() { - return id; - } - - public static final String ID = "version"; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index e00a8abc5c..da4cc87809 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -74,7 +74,7 @@ public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) } public Task loadAsync(DownloadProvider downloadProvider) { - return Task.ofThen(variables -> { + return Task.ofThen(() -> { lock.readLock().lock(); boolean loaded; @@ -88,7 +88,7 @@ public Task loadAsync(DownloadProvider downloadProvider) { } public Task loadAsync(String gameVersion, DownloadProvider downloadProvider) { - return Task.ofThen(variables -> { + return Task.ofThen(() -> { lock.readLock().lock(); boolean loaded; 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 2843c56b3d..c29de94a50 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 @@ -82,11 +82,6 @@ public Collection getDependencies() { return Collections.singleton(dependency); } - @Override - public String getId() { - return "version"; - } - @Override public boolean isRelyingOnDependencies() { return false; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index 8dc7f8a9f8..fe1250485a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -89,11 +89,6 @@ public List getDependencies() { return dependencies; } - @Override - public String getId() { - return "version"; - } - @Override public boolean doPreExecute() { return true; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java index fca62abec2..1c961c91d4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java @@ -49,11 +49,6 @@ public List getDependencies() { return dependencies; } - @Override - public String getId() { - return "version"; - } - @Override public boolean doPreExecute() { return true; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java index fcc33b1376..23d586c1e0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java @@ -33,15 +33,9 @@ public class LibrariesUniqueTask extends TaskResult { private final Version version; - private final String id; public LibrariesUniqueTask(Version version) { - this(version, "version"); - } - - public LibrariesUniqueTask(Version version, String id) { this.version = version; - this.id = id; } @Override @@ -99,9 +93,4 @@ public void execute() { setResult(version.setLibraries(multimap.values().stream().sorted().collect(Collectors.toList()))); } - - @Override - public String getId() { - return id; - } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index d60b529273..d24bc5a6a3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -22,6 +22,7 @@ import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.io.NetworkUtils; import java.util.Collection; @@ -32,7 +33,7 @@ * * @author huangyuhui */ -public final class VersionJsonDownloadTask extends Task { +public final class VersionJsonDownloadTask extends TaskResult { private final String gameVersion; private final DefaultDependencyManager dependencyManager; private final List dependents = new LinkedList<>(); @@ -65,8 +66,6 @@ public void execute() { RemoteVersion remoteVersion = gameVersionList.getVersions(gameVersion).stream().findFirst() .orElseThrow(() -> new IllegalStateException("Cannot find specific version " + gameVersion + " in remote repository")); String jsonURL = dependencyManager.getDownloadProvider().injectURL(remoteVersion.getUrl()); - dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL), ID)); + dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL)).storeTo(this::setResult)); } - - public static final String ID = "raw_version_json"; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java index d1031742b8..d404994b54 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java @@ -19,7 +19,7 @@ import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -31,7 +31,7 @@ * * @author huangyuhui */ -public final class VersionJsonSaveTask extends Task { +public final class VersionJsonSaveTask extends TaskResult { private final DefaultGameRepository repository; private final Version version; @@ -47,6 +47,7 @@ public VersionJsonSaveTask(DefaultGameRepository repository, Version version) { this.version = version; setSignificance(TaskSignificance.MODERATE); + setResult(version); } @Override 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 f62c77c17c..558714f954 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 @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.liteloader; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.LibrariesDownloadInfo; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.LibraryDownloadInfo; @@ -61,11 +60,6 @@ public Collection getDependencies() { return dependencies; } - @Override - public String getId() { - return "version"; - } - @Override public void execute() { Library library = new Library( 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 e9c10ea6da..716ddfad45 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 @@ -59,11 +59,6 @@ public Collection getDependencies() { return dependencies; } - @Override - public String getId() { - return "version"; - } - @Override public boolean isRelyingOnDependencies() { return false; 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 b9c6b06eac..c453ce8591 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -156,7 +156,7 @@ public void execute() throws Exception { } } - dependencies.add(new MaintainTask(version).then(var -> new VersionJsonSaveTask(repository, var.get(MaintainTask.ID)))); + dependencies.add(new MaintainTask(version).thenTaskResult(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion))); dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name))); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java index c327054912..f9d87efe73 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java @@ -18,57 +18,53 @@ package org.jackhuang.hmcl.task; import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.function.ExceptionalFunction; +import org.jackhuang.hmcl.util.function.ExceptionalSupplier; import java.util.Collection; import java.util.Collections; -import java.util.LinkedList; -import java.util.List; /** * A task that combines two tasks and make sure [pred] runs before succ. * * @author huangyuhui */ -final class CoupleTask

extends Task { +final class CoupleTask extends Task { private final boolean relyingOnDependents; - private final Collection dependents; - private final List dependencies = new LinkedList<>(); - private final ExceptionalFunction, Task, ?> succ; + private final Task pred; + private Task succ; + private final ExceptionalSupplier supplier; /** * A task that combines two tasks and make sure pred runs before succ. * - * @param pred the task that runs before succ. - * @param succ a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. + * @param pred the task that runs before supplier. + * @param supplier a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. * @param relyingOnDependents true if this task chain will be broken when task pred fails. */ - public CoupleTask(P pred, ExceptionalFunction, Task, ?> succ, boolean relyingOnDependents) { - this.dependents = pred == null ? Collections.emptySet() : Collections.singleton(pred); - this.succ = succ; + CoupleTask(Task pred, ExceptionalSupplier supplier, boolean relyingOnDependents) { + this.pred = pred; + this.supplier = supplier; this.relyingOnDependents = relyingOnDependents; setSignificance(TaskSignificance.MODERATE); - setName(succ.toString()); + setName(supplier.toString()); } @Override public void execute() throws Exception { - setName(succ.toString()); - Task task = succ.apply(getVariables()); - if (task != null) - dependencies.add(task); + setName(supplier.toString()); + succ = supplier.get(); } @Override public Collection getDependents() { - return dependents; + return pred == null ? Collections.emptySet() : Collections.singleton(pred); } @Override public Collection getDependencies() { - return dependencies; + return succ == null ? Collections.emptySet() : Collections.singleton(succ); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java index fd37f20e7b..a060d0d7c1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java @@ -37,13 +37,12 @@ final class FinalizedTask extends Task { * @param pred the task that runs before succ. * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. */ - public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback, String name) { + public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback) { this.pred = pred; this.scheduler = scheduler; this.callback = callback; setSignificance(TaskSignificance.MODERATE); - setName(name); } @Override 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 d391b65df1..376d3914a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -72,11 +72,6 @@ public Scheduler getScheduler() { return Schedulers.io(); } - @Override - public String getId() { - return id; - } - public GetTask setCacheRepository(CacheRepository repository) { this.repository = repository; return this; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java index 6386aba09b..f8bd7f3d97 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java @@ -17,8 +17,7 @@ */ package org.jackhuang.hmcl.task; -import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.function.ExceptionalConsumer; +import org.jackhuang.hmcl.util.function.ExceptionalRunnable; /** * @@ -26,16 +25,16 @@ */ class SimpleTask extends Task { - private final ExceptionalConsumer, ?> consumer; + private final ExceptionalRunnable closure; private final Scheduler scheduler; - public SimpleTask(String name, ExceptionalConsumer, ?> consumer, Scheduler scheduler) { - this.consumer = consumer; + public SimpleTask(String name, ExceptionalRunnable closure, Scheduler scheduler) { + this.closure = closure; this.scheduler = scheduler; if (name == null) { setSignificance(TaskSignificance.MINOR); - setName(consumer.toString()); + setName(closure.toString()); } else { setName(name); } @@ -48,6 +47,6 @@ public Scheduler getScheduler() { @Override public void execute() throws Exception { - consumer.accept(getVariables()); + closure.run(); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java index 393a3272c8..22111f6543 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java @@ -17,24 +17,30 @@ */ package org.jackhuang.hmcl.task; +import org.jackhuang.hmcl.util.AutoTypingMap; +import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; -public final class SimpleTaskResult extends TaskResult { - private final String id; - private final ExceptionalSupplier supplier; +import java.util.concurrent.Callable; - public SimpleTaskResult(String id, ExceptionalSupplier supplier) { - this.id = id; - this.supplier = supplier; +/** + * + * @author huangyuhui + */ +class SimpleTaskResult extends TaskResult { + + private final Callable callable; + + public SimpleTaskResult(Callable callable) { + this.callable = callable; } - @Override - public void execute() throws Exception { - setResult(supplier.get()); + public SimpleTaskResult(ExceptionalSupplier supplier) { + this.callable = supplier.toCallable(); } @Override - public String getId() { - return id; + public void execute() throws Exception { + setResult(callable.call()); } } 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 b719b0a67f..c43ab0d3bb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -23,13 +23,12 @@ import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.ReadOnlyStringWrapper; import org.jackhuang.hmcl.event.EventManager; -import org.jackhuang.hmcl.util.AutoTypingMap; import org.jackhuang.hmcl.util.InvocationDispatcher; import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.ReflectionHelper; import org.jackhuang.hmcl.util.function.ExceptionalConsumer; -import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; +import org.jackhuang.hmcl.util.function.ExceptionalSupplier; import java.util.Collection; import java.util.Collections; @@ -134,16 +133,6 @@ public Task setName(String name) { return this; } - private AutoTypingMap variables = null; - - public AutoTypingMap getVariables() { - return variables; - } - - void setVariables(AutoTypingMap variables) { - this.variables = variables; - } - public boolean doPreExecute() { return false; } @@ -280,16 +269,8 @@ public final void subscribe(Task subscriber) { new TaskExecutor(then(subscriber)).start(); } - public final void subscribe(Scheduler scheduler, ExceptionalConsumer, ?> closure) { - subscribe(of(scheduler, closure)); - } - public final void subscribe(Scheduler scheduler, ExceptionalRunnable closure) { - subscribe(of(scheduler, ExceptionalConsumer.fromRunnable(closure))); - } - - public final void subscribe(ExceptionalConsumer, ?> closure) { - subscribe(of(closure)); + subscribe(of(scheduler, closure)); } public final void subscribe(ExceptionalRunnable closure) { @@ -300,16 +281,36 @@ public final Task then(Task b) { return then(convert(b)); } - public final Task then(ExceptionalFunction, Task, ?> b) { - return new CoupleTask<>(this, b, true); + public final Task then(ExceptionalSupplier b) { + return new CoupleTask(this, b, true); + } + + public final TaskResult thenResult(Callable supplier) { + return thenTaskResult(() -> Task.ofResult(supplier)); + } + + public final TaskResult thenTaskResult(ExceptionalSupplier, ?> taskSupplier) { + return new TaskResult() { + TaskResult then; + + @Override + public void execute() throws Exception { + then = taskSupplier.get().storeTo(this::setResult); + } + + @Override + public Collection getDependencies() { + return then == null ? Collections.emptyList() : Collections.singleton(then); + } + }; } public final Task with(Task b) { return with(convert(b)); } - public final Task with(ExceptionalFunction, Task, E> b) { - return new CoupleTask<>(this, b, false); + public final Task with(ExceptionalSupplier b) { + return new CoupleTask(this, b, false); } public final Task finalized(FinalizedCallback b) { @@ -317,7 +318,7 @@ public final Task finalized(FinalizedCallback b) { } public final Task finalized(Scheduler scheduler, FinalizedCallback b) { - return new FinalizedTask(this, scheduler, b, ReflectionHelper.getCaller().toString()); + return new FinalizedTask(this, scheduler, b).setName(getCaller()); } // T, K here is necessary, or javac cannot infer type of failure @@ -339,58 +340,38 @@ public final Task finalized(Scheduler }); } - public static Task of(String name, ExceptionalRunnable runnable) { - return of(name, ExceptionalConsumer.fromRunnable(runnable)); - } - - public static Task of(ExceptionalRunnable runnable) { - return of(ExceptionalConsumer.fromRunnable(runnable)); - } - - public static Task of(String name, ExceptionalConsumer, ?> closure) { - return of(name, Schedulers.defaultScheduler(), closure); - } - - public static Task of(ExceptionalConsumer, ?> closure) { + public static Task of(ExceptionalRunnable closure) { return of(Schedulers.defaultScheduler(), closure); } - public static Task of(String name, Scheduler scheduler, ExceptionalConsumer, ?> closure) { - return new SimpleTask(name, closure, scheduler); + public static Task of(String name, ExceptionalRunnable closure) { + return of(name, Schedulers.defaultScheduler(), closure); } - public static Task of(Scheduler scheduler, ExceptionalConsumer, ?> closure) { - return of(ReflectionHelper.getCaller().toString(), scheduler, closure); + public static Task of(Scheduler scheduler, ExceptionalRunnable closure) { + return of(getCaller(), scheduler, closure); } public static Task of(String name, Scheduler scheduler, ExceptionalRunnable closure) { - return new SimpleTask(name, ExceptionalConsumer.fromRunnable(closure), scheduler); - } - - public static Task of(Scheduler scheduler, ExceptionalRunnable closure) { - return of(ReflectionHelper.getCaller().toString(), scheduler, closure); + return new SimpleTask(name, closure, scheduler); } - public static Task ofThen(ExceptionalFunction, Task, ?> b) { - return new CoupleTask<>(null, b, true); + public static Task ofThen(ExceptionalSupplier b) { + return new CoupleTask(null, b, true); } public static TaskResult ofResult(Callable callable) { - return ofResult("", callable); - } - - public static TaskResult ofResult(String id, Callable callable) { - return new TaskCallable<>(id, callable); + return ofResult(getCaller(), callable); } - public static TaskResult ofResult(String id, ExceptionalFunction, V, ?> closure) { - return new TaskCallable<>(id, closure); + public static TaskResult ofResult(String name, Callable callable) { + return new SimpleTaskResult<>(callable).setName(name); } - private static ExceptionalFunction, Task, ?> convert(Task t) { - return new ExceptionalFunction, Task, Exception>() { + private static ExceptionalSupplier convert(Task t) { + return new ExceptionalSupplier() { @Override - public Task apply(AutoTypingMap autoTypingMap) { + public Task get() { return t; } @@ -426,4 +407,8 @@ public enum TaskState { public interface FinalizedCallback { void execute(boolean isDependentsSucceeded, Exception exception) throws Exception; } + + static String getCaller() { + return ReflectionHelper.getCaller(packageName -> !"org.jackhuang.hmcl.task".equals(packageName)).toString(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskCallable.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskCallable.java deleted file mode 100644 index 1b7e85432d..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskCallable.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.function.ExceptionalFunction; - -import java.util.concurrent.Callable; - -/** - * - * @author huangyuhui - */ -class TaskCallable extends TaskResult { - - private final String id; - private final ExceptionalFunction, V, ?> callable; - - public TaskCallable(String id, Callable callable) { - this(id, variables -> callable.call()); - } - - public TaskCallable(String id, ExceptionalFunction, V, ?> callable) { - this.id = id; - this.callable = callable; - } - - @Override - public String getId() { - return id; - } - - @Override - public void execute() throws Exception { - setResult(callable.apply(getVariables())); - } -} 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 074e1c1615..12587b7158 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -38,7 +38,6 @@ public final class TaskExecutor { private Exception lastException; private final AtomicInteger totTask = new AtomicInteger(0); private final ConcurrentLinkedQueue> workerQueue = new ConcurrentLinkedQueue<>(); - private final AutoTypingMap variables = new AutoTypingMap<>(new HashMap<>()); private Scheduler scheduler = Schedulers.newThread(); public TaskExecutor(Task task) { @@ -147,8 +146,6 @@ private boolean executeTask(Task task) { boolean flag = false; try { - task.setVariables(variables); - if (task.doPreExecute()) { try { task.getScheduler().schedule(task::preExecute).get(); @@ -186,11 +183,6 @@ private boolean executeTask(Task task) { task.setState(Task.TaskState.EXECUTED); } - if (task instanceof TaskResult) { - TaskResult taskResult = (TaskResult) task; - variables.set(taskResult.getId(), taskResult.getResult()); - } - Collection dependencies = task.getDependencies(); boolean doDependenciesSucceeded = executeTasks(dependencies); Exception dependenciesException = dependencies.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); @@ -238,8 +230,6 @@ private boolean executeTask(Task task) { } task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); - } finally { - task.setVariables(null); } task.setState(flag ? Task.TaskState.SUCCEEDED : Task.TaskState.FAILED); return flag; @@ -249,10 +239,6 @@ public int getRunningTasks() { return totTask.get(); } - public AutoTypingMap getVariables() { - return variables; - } - private class Invoker implements ExceptionalRunnable { private final Task task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index 46f2ecc556..5f9185ae0e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -17,12 +17,12 @@ */ package org.jackhuang.hmcl.task; -import org.jackhuang.hmcl.util.ReflectionHelper; import org.jackhuang.hmcl.util.function.ExceptionalConsumer; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import java.util.Collection; import java.util.Collections; +import java.util.function.Consumer; /** * A task that has a result. @@ -32,6 +32,13 @@ public abstract class TaskResult extends Task { private V result; + private Consumer resultConsumer; + + @Override + public TaskResult setName(String name) { + super.setName(name); + return this; + } public V getResult() { return result; @@ -39,20 +46,59 @@ public V getResult() { public void setResult(V result) { this.result = result; + if (resultConsumer != null) + resultConsumer.accept(result); + } + + public TaskResult storeTo(Consumer resultConsumer) { + this.resultConsumer = resultConsumer; + return this; } - public abstract String getId(); + public TaskResult thenTaskResult(ExceptionalFunction, E> taskSupplier) { + return new TaskResult() { + TaskResult then; + + @Override + public Collection getDependents() { + return Collections.singleton(TaskResult.this); + } + + @Override + public void execute() throws Exception { + then = taskSupplier.apply(TaskResult.this.getResult()).storeTo(this::setResult); + } + + @Override + public Collection getDependencies() { + return then == null ? Collections.emptyList() : Collections.singleton(then); + } + }; + } + + public Task then(ExceptionalFunction taskSupplier) { + return new CoupleTask(this, () -> taskSupplier.apply(getResult()), true); + } public TaskResult thenResult(ExceptionalFunction task) { return thenResult(Schedulers.defaultScheduler(), task); } public TaskResult thenResult(Scheduler scheduler, ExceptionalFunction task) { - return thenResult(ReflectionHelper.getCaller().toString(), scheduler, task); + return thenResult(getCaller(), scheduler, task); } - public TaskResult thenResult(String id, Scheduler scheduler, ExceptionalFunction task) { - return new Subtask<>(id, scheduler, task); + public TaskResult thenResult(String name, Scheduler scheduler, ExceptionalFunction task) { + return new Subtask<>(name, scheduler, task); + } + + // stupid javac stop us from renaming thenVoid to thenResult + public Task thenVoid(ExceptionalConsumer task) { + return thenVoid(Schedulers.defaultScheduler(), task); + } + + public Task thenVoid(Scheduler scheduler, ExceptionalConsumer task) { + return new CoupleTask(this, () -> Task.of(scheduler, () -> task.accept(getResult())), true); } public Task finalized(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { @@ -64,14 +110,14 @@ public Task finalized(Scheduler scheduler, FinalizedCallback callback) { } private class Subtask extends TaskResult { - private final String id; private final Scheduler scheduler; private final ExceptionalFunction callable; - public Subtask(String id, Scheduler scheduler, ExceptionalFunction callable) { - this.id = id; + public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { this.scheduler = scheduler; this.callable = callable; + + setName(name); } @Override @@ -79,11 +125,6 @@ public Collection getDependents() { return Collections.singleton(TaskResult.this); } - @Override - public String getId() { - return id; - } - @Override public Scheduler getScheduler() { return scheduler; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.java index aa497f936b..12e24507e0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.java @@ -17,17 +17,28 @@ */ package org.jackhuang.hmcl.util; +import java.util.function.Predicate; + /** * * @author huangyuhui */ public final class ReflectionHelper { - public static StackTraceElement getCaller() { + /** + * Get caller, this method is caller sensitive. + * @param packageFilter returns false if we consider the given package is internal calls, not the caller + * @return the caller, method name, source file, line number + */ + public static StackTraceElement getCaller(Predicate packageFilter) { StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + // element[0] is Thread.currentThread().getStackTrace() + // element[1] is ReflectionHelper.getCaller(packageFilter) + // so element[2] is caller of this method. StackTraceElement caller = elements[2]; for (int i = 3; i < elements.length; ++i) { - if (!caller.getClassName().equals(elements[i].getClassName())) + if (packageFilter.test(StringUtils.substringBeforeLast(elements[i].getClassName(), '.')) && + !caller.getClassName().equals(elements[i].getClassName())) return elements[i]; } return caller; From 9add2387b9c60d2e1f55996e8b14f3d5182f2eea Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 23 Feb 2019 23:42:05 +0800 Subject: [PATCH 0043/2639] Add comments to FileUtils and IOUtils --- .../download/game/LibraryDownloadTask.java | 12 ++-- .../download/game/VersionJsonSaveTask.java | 2 - .../hmcl/game/DefaultGameRepository.java | 4 +- .../jackhuang/hmcl/mod/ForgeModMetadata.java | 4 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 18 ++--- .../java/org/jackhuang/hmcl/task/Task.java | 5 ++ .../org/jackhuang/hmcl/util/io/FileUtils.java | 67 ++++++++++++++----- .../org/jackhuang/hmcl/util/io/IOUtils.java | 17 ++++- 8 files changed, 91 insertions(+), 38 deletions(-) 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 fecb40e3f0..311ffaa1a8 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 @@ -225,16 +225,16 @@ private static void unpackLibrary(File dest, byte[] src) throws IOException { int x = decompressed.length; int len = decompressed[(x - 8)] & 0xFF | (decompressed[(x - 7)] & 0xFF) << 8 | (decompressed[(x - 6)] & 0xFF) << 16 | (decompressed[(x - 5)] & 0xFF) << 24; - File temp = FileUtils.createTempFile("minecraft", ".pack"); + Path temp = Files.createTempFile("minecraft", ".pack"); byte[] checksums = Arrays.copyOfRange(decompressed, decompressed.length - len - 8, decompressed.length - 8); - OutputStream out = new FileOutputStream(temp); - out.write(decompressed, 0, decompressed.length - len - 8); - out.close(); + try (OutputStream out = Files.newOutputStream(temp)) { + out.write(decompressed, 0, decompressed.length - len - 8); + } try (FileOutputStream jarBytes = new FileOutputStream(dest); JarOutputStream jos = new JarOutputStream(jarBytes)) { - Pack200.newUnpacker().unpack(temp, jos); + Pack200.newUnpacker().unpack(temp.toFile(), jos); JarEntry checksumsFile = new JarEntry("checksums.sha1"); checksumsFile.setTime(0L); @@ -243,6 +243,6 @@ private static void unpackLibrary(File dest, byte[] src) throws IOException { jos.closeEntry(); } - temp.delete(); + Files.delete(temp); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java index d404994b54..00a14543e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java @@ -53,8 +53,6 @@ public VersionJsonSaveTask(DefaultGameRepository repository, Version version) { @Override public void execute() throws Exception { File json = repository.getVersionJson(version.getId()).getAbsoluteFile(); - if (!FileUtils.makeFile(json)) - throw new IOException("Cannot create file " + json); FileUtils.writeText(json, JsonUtils.GSON.toJson(version)); } } 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 f20eda3cfd..39ee352e3f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -168,8 +168,8 @@ public boolean removeVersionFromDisk(String id) { versions.remove(id); - if (FileUtils.isMovingToTrashSupported()) { - return FileUtils.moveToTrash(removedFile); + if (FileUtils.isMovingToTrashSupported() && FileUtils.moveToTrash(removedFile)) { + return true; } // remove json files first to ensure HMCL will not recognize this folder as a valid version. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ForgeModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ForgeModMetadata.java index 7880b47ffe..e0f4105ea8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ForgeModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ForgeModMetadata.java @@ -23,7 +23,7 @@ import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; -import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; @@ -119,7 +119,7 @@ public static ModInfo fromFile(ModManager modManager, File modFile) throws IOExc Path mcmod = fs.getPath("mcmod.info"); if (Files.notExists(mcmod)) throw new IOException("File " + modFile + " is not a Forge mod."); - List modList = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(Files.newInputStream(mcmod)), + List modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), new TypeToken>() { }.getType()); if (modList == null || modList.isEmpty()) 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 92ecbe5801..7829d02b05 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -33,6 +33,7 @@ import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; import java.util.Optional; @@ -212,7 +213,7 @@ public void execute() throws Exception { break; } - File temp = null; + Path temp = null; try { updateProgress(0); @@ -242,15 +243,15 @@ public void execute() throws Exception { if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) throw new IOException("Could not make directory " + file.getAbsoluteFile().getParent()); - temp = FileUtils.createTempFile(); - rFile = new RandomAccessFile(temp, "rw"); + temp = Files.createTempFile(null, null); + rFile = new RandomAccessFile(temp.toFile(), "rw"); MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest(); stream = con.getInputStream(); int lastDownloaded = 0, downloaded = 0; long lastTime = System.currentTimeMillis(); - byte buffer[] = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; + byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; while (true) { if (Thread.interrupted()) { Thread.currentThread().interrupt(); @@ -283,16 +284,15 @@ public void execute() throws Exception { // Restore temp file to original name. if (Thread.interrupted()) { - temp.delete(); + temp.toFile().delete(); Thread.currentThread().interrupt(); break; } else { - if (file.exists() && !file.delete()) - throw new IOException("Unable to delete existent file " + file); + Files.deleteIfExists(file.toPath()); if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) throw new IOException("Unable to make parent directory " + file); try { - FileUtils.moveFile(temp, file); + FileUtils.moveFile(temp.toFile(), file); } catch (Exception e) { throw new IOException("Unable to move temp file from " + temp + " to " + file, e); } @@ -321,7 +321,7 @@ public void execute() throws Exception { return; } catch (IOException | IllegalStateException e) { if (temp != null) - temp.delete(); + temp.toFile().delete(); exception = e; } finally { closeFiles(); 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 c43ab0d3bb..cede8eebc7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -293,6 +293,11 @@ public final TaskResult thenTaskResult(ExceptionalSupplier, return new TaskResult() { TaskResult then; + @Override + public Collection getDependents() { + return Collections.singleton(Task.this); + } + @Override public void execute() throws Exception { then = taskSupplier.get().storeTo(this::setResult); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java index 52fe65a8f4..a38e53f2fe 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java @@ -116,14 +116,43 @@ public static String readText(Path file, Charset charset) throws IOException { return new String(Files.readAllBytes(file), charset); } + /** + * Write plain text to file. Characters are encoded into bytes using UTF-8. + * + * We don't care about platform difference of line separator. Because readText accept all possibilities of line separator. + * It will create the file if it does not exist, or truncate the existing file to empty for rewriting. + * All characters in text will be written into the file in binary format. Existing data will be erased. + * @param file the path to the file + * @param text the text being written to file + * @throws IOException if an I/O error occurs + */ public static void writeText(File file, String text) throws IOException { writeText(file, text, UTF_8); } + /** + * Write plain text to file. + * + * We don't care about platform difference of line separator. Because readText accept all possibilities of line separator. + * It will create the file if it does not exist, or truncate the existing file to empty for rewriting. + * All characters in text will be written into the file in binary format. Existing data will be erased. + * @param file the path to the file + * @param text the text being written to file + * @param charset the charset to use for encoding + * @throws IOException if an I/O error occurs + */ public static void writeText(File file, String text, Charset charset) throws IOException { writeBytes(file, text.getBytes(charset)); } + /** + * Write byte array to file. + * It will create the file if it does not exist, or truncate the existing file to empty for rewriting. + * All bytes in byte array will be written into the file in binary format. Existing data will be erased. + * @param file the path to the file + * @param array the data being written to file + * @throws IOException if an I/O error occurs + */ public static void writeBytes(File file, byte[] array) throws IOException { Files.createDirectories(file.toPath().getParent()); Files.write(file.toPath(), array); @@ -153,6 +182,14 @@ public static boolean deleteDirectoryQuietly(File directory) { } } + /** + * Copy directory. + * Paths of all files relative to source directory will be the same as the ones relative to destination directory. + * + * @param src the source directory. + * @param dest the destination directory, which will be created if not existing. + * @throws IOException if an I/O error occurs. + */ public static void copyDirectory(Path src, Path dest) throws IOException { Files.walkFileTree(src, new SimpleFileVisitor(){ @Override @@ -173,6 +210,20 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th }); } + /** + * Move file to trash. + * + * This method is only implemented in Java 9. Please check we are using Java 9 by invoking isMovingToTrashSupported. + * Example: + *

{@code
+     * if (FileUtils.isMovingToTrashSupported()) {
+     *     FileUtils.moveToTrash(file);
+     * }
+     * }
+ * @param file the file being moved to trash. + * @see FileUtils#isMovingToTrashSupported() + * @return false if moveToTrash does not exist, or platform does not support Desktop.Action.MOVE_TO_TRASH + */ public static boolean moveToTrash(File file) { try { java.awt.Desktop desktop = java.awt.Desktop.getDesktop(); @@ -314,20 +365,4 @@ public static List listFilesByExtension(File file, String extension) { result.add(it); return result; } - - public static File createTempFile() throws IOException { - return createTempFile("tmp"); - } - - public static File createTempFile(String prefix) throws IOException { - return createTempFile(prefix, null); - } - - public static File createTempFile(String prefix, String suffix) throws IOException { - return createTempFile(prefix, suffix, null); - } - - public static File createTempFile(String prefix, String suffix, File directory) throws IOException { - return File.createTempFile(prefix, suffix, directory); - } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/IOUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/IOUtils.java index e5421a2c3a..25d085c0eb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/IOUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/IOUtils.java @@ -21,8 +21,9 @@ import java.nio.charset.Charset; /** + * This utility class consists of some util methods operating on InputStream/OutputStream. * - * @author huang + * @author huangyuhui */ public final class IOUtils { @@ -31,12 +32,26 @@ private IOUtils() { public static final int DEFAULT_BUFFER_SIZE = 8 * 1024; + /** + * Read all bytes to a buffer from given input stream. The stream will not be closed. + * + * @param stream the InputStream being read. + * @return all bytes read from the stream + * @throws IOException if an I/O error occurs. + */ public static byte[] readFullyWithoutClosing(InputStream stream) throws IOException { ByteArrayOutputStream result = new ByteArrayOutputStream(); copyTo(stream, result); return result.toByteArray(); } + /** + * Read all bytes to a buffer from given input stream, and close the input stream finally. + * + * @param stream the InputStream being read, closed finally. + * @return all bytes read from the stream + * @throws IOException if an I/O error occurs. + */ public static ByteArrayOutputStream readFully(InputStream stream) throws IOException { try (InputStream is = stream) { ByteArrayOutputStream result = new ByteArrayOutputStream(); From 84fbca7905dce88fbb8728736ac491bff48e6dfa Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 23 Feb 2019 23:48:23 +0800 Subject: [PATCH 0044/2639] Remove unused code --- .../hmcl/game/HMCLGameRepository.java | 3 - .../jackhuang/hmcl/game/LauncherHelper.java | 24 +-- .../org/jackhuang/hmcl/setting/Profile.java | 10 +- .../hmcl/setting/VersionSetting.java | 101 +++++----- .../org/jackhuang/hmcl/ui/Controllers.java | 7 +- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 10 +- .../org/jackhuang/hmcl/ui/SettingsPage.java | 4 +- .../hmcl/ui/construct/MessageBox.java | 172 ------------------ .../hmcl/ui/construct/MessageDialogPane.java | 23 ++- .../ui/download/InstallerWizardProvider.java | 8 +- .../ModpackInstallWizardProvider.java | 12 +- .../hmcl/ui/download/ModpackPage.java | 4 +- .../hmcl/ui/versions/VersionSettingsPage.java | 27 +-- .../TaskExecutorDialogWizardDisplayer.java | 10 +- .../jackhuang/hmcl/upgrade/UpdateHandler.java | 6 +- .../jackhuang/hmcl/util/CrashReporter.java | 9 +- .../org/jackhuang/hmcl/util/i18n/Locales.java | 4 - .../download/game/VersionJsonSaveTask.java | 3 - .../java/org/jackhuang/hmcl/mod/ModInfo.java | 10 +- .../java/org/jackhuang/hmcl/util/Lang.java | 22 --- .../util/javafx/ImmediateBooleanProperty.java | 55 ------ .../util/javafx/ImmediateIntegerProperty.java | 55 ------ .../util/javafx/ImmediateObjectProperty.java | 55 ------ .../util/javafx/ImmediateStringProperty.java | 75 -------- 24 files changed, 145 insertions(+), 564 deletions(-) delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateBooleanProperty.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateIntegerProperty.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateObjectProperty.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateStringProperty.java 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 563aba480a..6390e31ca4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -20,9 +20,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import javafx.scene.image.Image; -import org.jackhuang.hmcl.event.EventBus; -import org.jackhuang.hmcl.event.RefreshedVersionsEvent; -import org.jackhuang.hmcl.event.RefreshingVersionsEvent; import org.jackhuang.hmcl.setting.EnumGameDirectory; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; 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 de641b771f..d684dbbbb3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -38,7 +38,7 @@ import org.jackhuang.hmcl.ui.DialogController; import org.jackhuang.hmcl.ui.LogWindow; import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.Log4jLevel; import org.jackhuang.hmcl.util.Logging; @@ -236,7 +236,7 @@ public void onStop(boolean success, TaskExecutor executor) { } Controllers.dialog(message, scriptFile == null ? i18n("launch.failed") : i18n("version.launch_script.failed"), - MessageBox.ERROR_MESSAGE); + MessageType.ERROR); } } }); @@ -263,7 +263,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse("Unknown")); JavaVersion java = setting.getJavaVersion(); if (java == null) { - Controllers.dialog(i18n("launch.wrong_javadir"), i18n("message.warning"), MessageBox.WARNING_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.wrong_javadir"), i18n("message.warning"), MessageType.WARNING, onAccept); setting.setJava(null); setting.setDefaultJavaPath(null); java = JavaVersion.fromCurrentEnvironment(); @@ -282,10 +282,10 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers if (gameVersion.compareTo(VersionNumber.asVersion("1.13")) >= 0) { // Minecraft 1.13 and later versions only support Java 8 or later. // Terminate launching operation. - Controllers.dialog(i18n("launch.advice.java8_1_13"), i18n("message.error"), MessageBox.ERROR_MESSAGE, null); + Controllers.dialog(i18n("launch.advice.java8_1_13"), i18n("message.error"), MessageType.ERROR, null); } else { // Most mods require Java 8 or later version. - Controllers.dialog(i18n("launch.advice.newer_java"), i18n("message.warning"), MessageBox.WARNING_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.newer_java"), i18n("message.warning"), MessageType.WARNING, onAccept); } flag = true; } @@ -301,10 +301,10 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers if (java8.isPresent()) { java8required = true; setting.setJavaVersion(java8.get()); - Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.corrected"), i18n("message.info"), MessageBox.INFORMATION_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.corrected"), i18n("message.info"), MessageType.INFORMATION, onAccept); flag = true; } else { - Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.uncorrected"), i18n("message.error"), MessageBox.ERROR_MESSAGE, null); + Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.uncorrected"), i18n("message.error"), MessageType.ERROR, null); flag = true; } } @@ -319,7 +319,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers newJavaRequired = true; setting.setJavaVersion(java8.get()); } else { - Controllers.dialog(i18n("launch.advice.java8_51_1_13"), i18n("message.warning"), MessageBox.WARNING_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.java8_51_1_13"), i18n("message.warning"), MessageType.WARNING, onAccept); flag = true; } } @@ -351,7 +351,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers if (java64.isPresent()) { setting.setJavaVersion(java64.get()); } else { - Controllers.dialog(i18n("launch.advice.different_platform"), i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.different_platform"), i18n("message.error"), MessageType.ERROR, onAccept); flag = true; } } @@ -361,13 +361,13 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers setting.getMaxMemory() > 1.5 * 1024) { // 1.5 * 1024 is an inaccurate number. // Actual memory limit depends on operating system and memory. - Controllers.dialog(i18n("launch.advice.too_large_memory_for_32bit"), i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.too_large_memory_for_32bit"), i18n("message.error"), MessageType.ERROR, onAccept); flag = true; } // Cannot allocate too much memory exceeding free space. if (!flag && OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { - Controllers.dialog(i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), i18n("message.error"), MessageType.ERROR, onAccept); flag = true; } @@ -379,7 +379,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers VersionNumber.VERSION_COMPARATOR.compare(it.getVersion(), "1.12.2-14.23.5.2773") < 0); boolean hasLiteLoader = version.getLibraries().stream().anyMatch(it -> it.is("com.mumfrey", "liteloader")); if (hasForge2760 && hasLiteLoader && gameVersion.compareTo(VersionNumber.asVersion("1.12.2")) == 0) { - Controllers.dialog(i18n("launch.advice.forge2760_liteloader"), i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept); + Controllers.dialog(i18n("launch.advice.forge2760_liteloader"), i18n("message.error"), MessageType.ERROR, onAccept); flag = true; } } 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 8b12ff90dc..29f87fea9a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -33,8 +33,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.ui.WeakListenerHolder; import org.jackhuang.hmcl.util.*; -import org.jackhuang.hmcl.util.javafx.ImmediateObjectProperty; -import org.jackhuang.hmcl.util.javafx.ImmediateStringProperty; import org.jackhuang.hmcl.util.javafx.ObservableHelper; import java.io.File; @@ -90,9 +88,9 @@ public VersionSetting getGlobal() { return global.get(); } - private final ImmediateStringProperty name; + private final SimpleStringProperty name; - public ImmediateStringProperty nameProperty() { + public StringProperty nameProperty() { return name; } @@ -131,8 +129,8 @@ public Profile(String name, File initialGameDir, VersionSetting global) { } public Profile(String name, File initialGameDir, VersionSetting global, String selectedVersion, boolean useRelativePath) { - this.name = new ImmediateStringProperty(this, "name", name); - gameDir = new ImmediateObjectProperty<>(this, "gameDir", initialGameDir); + this.name = new SimpleStringProperty(this, "name", name); + gameDir = new SimpleObjectProperty<>(this, "gameDir", initialGameDir); repository = new HMCLGameRepository(this, initialGameDir); this.global.set(global == null ? new VersionSetting() : global); this.selectedVersion.set(selectedVersion); 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 8d2a44c50a..9fc8a766ee 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -21,13 +21,18 @@ import com.google.gson.annotations.JsonAdapter; import javafx.beans.InvalidationListener; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.game.LaunchOptions; import org.jackhuang.hmcl.util.*; -import org.jackhuang.hmcl.util.javafx.ImmediateBooleanProperty; -import org.jackhuang.hmcl.util.javafx.ImmediateIntegerProperty; -import org.jackhuang.hmcl.util.javafx.ImmediateObjectProperty; -import org.jackhuang.hmcl.util.javafx.ImmediateStringProperty; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; @@ -60,9 +65,9 @@ public void setGlobal(boolean global) { this.global = global; } - private final ImmediateBooleanProperty usesGlobalProperty = new ImmediateBooleanProperty(this, "usesGlobal", false); + private final BooleanProperty usesGlobalProperty = new SimpleBooleanProperty(this, "usesGlobal", false); - public ImmediateBooleanProperty usesGlobalProperty() { + public BooleanProperty usesGlobalProperty() { return usesGlobalProperty; } @@ -84,9 +89,9 @@ public void setUsesGlobal(boolean usesGlobal) { // java - private final ImmediateStringProperty javaProperty = new ImmediateStringProperty(this, "java", ""); + private final StringProperty javaProperty = new SimpleStringProperty(this, "java", ""); - public ImmediateStringProperty javaProperty() { + public StringProperty javaProperty() { return javaProperty; } @@ -110,7 +115,7 @@ public void setUsesCustomJavaDir() { setDefaultJavaPath(null); } - private final ImmediateStringProperty defaultJavaPathProperty = new ImmediateStringProperty(this, "defaultJavaPath", ""); + private final StringProperty defaultJavaPathProperty = new SimpleStringProperty(this, "defaultJavaPath", ""); /** * Path to Java executable, or null if user customizes java directory. @@ -124,9 +129,9 @@ public void setDefaultJavaPath(String defaultJavaPath) { defaultJavaPathProperty.set(defaultJavaPath); } - private final ImmediateStringProperty javaDirProperty = new ImmediateStringProperty(this, "javaDir", ""); + private final StringProperty javaDirProperty = new SimpleStringProperty(this, "javaDir", ""); - public ImmediateStringProperty javaDirProperty() { + public StringProperty javaDirProperty() { return javaDirProperty; } @@ -141,9 +146,9 @@ public void setJavaDir(String javaDir) { javaDirProperty.set(javaDir); } - private final ImmediateStringProperty wrapperProperty = new ImmediateStringProperty(this, "wrapper", ""); + private final StringProperty wrapperProperty = new SimpleStringProperty(this, "wrapper", ""); - public ImmediateStringProperty wrapperProperty() { + public StringProperty wrapperProperty() { return wrapperProperty; } @@ -158,9 +163,9 @@ public void setWrapper(String wrapper) { wrapperProperty.set(wrapper); } - private final ImmediateStringProperty permSizeProperty = new ImmediateStringProperty(this, "permSize", ""); + private final StringProperty permSizeProperty = new SimpleStringProperty(this, "permSize", ""); - public ImmediateStringProperty permSizeProperty() { + public StringProperty permSizeProperty() { return permSizeProperty; } @@ -175,9 +180,9 @@ public void setPermSize(String permSize) { permSizeProperty.set(permSize); } - private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", OperatingSystem.SUGGESTED_MEMORY); + private final IntegerProperty maxMemoryProperty = new SimpleIntegerProperty(this, "maxMemory", OperatingSystem.SUGGESTED_MEMORY); - public ImmediateIntegerProperty maxMemoryProperty() { + public IntegerProperty maxMemoryProperty() { return maxMemoryProperty; } @@ -195,9 +200,9 @@ public void setMaxMemory(int maxMemory) { /** * The minimum memory that JVM can allocate for heap. */ - private final ImmediateObjectProperty minMemoryProperty = new ImmediateObjectProperty<>(this, "minMemory", null); + private final ObjectProperty minMemoryProperty = new SimpleObjectProperty<>(this, "minMemory", null); - public ImmediateObjectProperty minMemoryProperty() { + public ObjectProperty minMemoryProperty() { return minMemoryProperty; } @@ -209,9 +214,9 @@ public void setMinMemory(Integer minMemory) { minMemoryProperty.set(minMemory); } - private final ImmediateStringProperty preLaunchCommandProperty = new ImmediateStringProperty(this, "precalledCommand", ""); + private final StringProperty preLaunchCommandProperty = new SimpleStringProperty(this, "precalledCommand", ""); - public ImmediateStringProperty preLaunchCommandProperty() { + public StringProperty preLaunchCommandProperty() { return preLaunchCommandProperty; } @@ -229,9 +234,9 @@ public void setPreLaunchCommand(String preLaunchCommand) { // options - private final ImmediateStringProperty javaArgsProperty = new ImmediateStringProperty(this, "javaArgs", ""); + private final StringProperty javaArgsProperty = new SimpleStringProperty(this, "javaArgs", ""); - public ImmediateStringProperty javaArgsProperty() { + public StringProperty javaArgsProperty() { return javaArgsProperty; } @@ -246,9 +251,9 @@ public void setJavaArgs(String javaArgs) { javaArgsProperty.set(javaArgs); } - private final ImmediateStringProperty minecraftArgsProperty = new ImmediateStringProperty(this, "minecraftArgs", ""); + private final StringProperty minecraftArgsProperty = new SimpleStringProperty(this, "minecraftArgs", ""); - public ImmediateStringProperty minecraftArgsProperty() { + public StringProperty minecraftArgsProperty() { return minecraftArgsProperty; } @@ -263,9 +268,9 @@ public void setMinecraftArgs(String minecraftArgs) { minecraftArgsProperty.set(minecraftArgs); } - private final ImmediateBooleanProperty noJVMArgsProperty = new ImmediateBooleanProperty(this, "noJVMArgs", false); + private final BooleanProperty noJVMArgsProperty = new SimpleBooleanProperty(this, "noJVMArgs", false); - public ImmediateBooleanProperty noJVMArgsProperty() { + public BooleanProperty noJVMArgsProperty() { return noJVMArgsProperty; } @@ -280,9 +285,9 @@ public void setNoJVMArgs(boolean noJVMArgs) { noJVMArgsProperty.set(noJVMArgs); } - private final ImmediateBooleanProperty notCheckJVMProperty = new ImmediateBooleanProperty(this, "notCheckJVM", false); + private final BooleanProperty notCheckJVMProperty = new SimpleBooleanProperty(this, "notCheckJVM", false); - public ImmediateBooleanProperty notCheckJVMProperty() { + public BooleanProperty notCheckJVMProperty() { return notCheckJVMProperty; } @@ -297,9 +302,9 @@ public void setNotCheckJVM(boolean notCheckJVM) { notCheckJVMProperty.set(notCheckJVM); } - private final ImmediateBooleanProperty notCheckGameProperty = new ImmediateBooleanProperty(this, "notCheckGame", false); + private final BooleanProperty notCheckGameProperty = new SimpleBooleanProperty(this, "notCheckGame", false); - public ImmediateBooleanProperty notCheckGameProperty() { + public BooleanProperty notCheckGameProperty() { return notCheckGameProperty; } @@ -314,9 +319,9 @@ public void setNotCheckGame(boolean notCheckGame) { notCheckGameProperty.set(notCheckGame); } - private final ImmediateBooleanProperty showLogsProperty = new ImmediateBooleanProperty(this, "showLogs", false); + private final BooleanProperty showLogsProperty = new SimpleBooleanProperty(this, "showLogs", false); - public ImmediateBooleanProperty showLogsProperty() { + public BooleanProperty showLogsProperty() { return showLogsProperty; } @@ -333,14 +338,14 @@ public void setShowLogs(boolean showLogs) { // Minecraft settings. - private final ImmediateStringProperty serverIpProperty = new ImmediateStringProperty(this, "serverIp", ""); + private final StringProperty serverIpProperty = new SimpleStringProperty(this, "serverIp", ""); - public ImmediateStringProperty serverIpProperty() { + public StringProperty serverIpProperty() { return serverIpProperty; } /** - * The server ip that will be entered after Minecraft successfully loaded immediately. + * The server ip that will be entered after Minecraft successfully loaded ly. * * Format: ip:port or without port. */ @@ -353,9 +358,9 @@ public void setServerIp(String serverIp) { } - private final ImmediateBooleanProperty fullscreenProperty = new ImmediateBooleanProperty(this, "fullscreen", false); + private final BooleanProperty fullscreenProperty = new SimpleBooleanProperty(this, "fullscreen", false); - public ImmediateBooleanProperty fullscreenProperty() { + public BooleanProperty fullscreenProperty() { return fullscreenProperty; } @@ -370,9 +375,9 @@ public void setFullscreen(boolean fullscreen) { fullscreenProperty.set(fullscreen); } - private final ImmediateIntegerProperty widthProperty = new ImmediateIntegerProperty(this, "width", 854); + private final IntegerProperty widthProperty = new SimpleIntegerProperty(this, "width", 854); - public ImmediateIntegerProperty widthProperty() { + public IntegerProperty widthProperty() { return widthProperty; } @@ -392,9 +397,9 @@ public void setWidth(int width) { } - private final ImmediateIntegerProperty heightProperty = new ImmediateIntegerProperty(this, "height", 480); + private final IntegerProperty heightProperty = new SimpleIntegerProperty(this, "height", 480); - public ImmediateIntegerProperty heightProperty() { + public IntegerProperty heightProperty() { return heightProperty; } @@ -417,9 +422,9 @@ public void setHeight(int height) { * 0 - .minecraft
* 1 - .minecraft/versions/<version>/
*/ - private final ImmediateObjectProperty gameDirTypeProperty = new ImmediateObjectProperty<>(this, "gameDirType", EnumGameDirectory.ROOT_FOLDER); + private final ObjectProperty gameDirTypeProperty = new SimpleObjectProperty<>(this, "gameDirType", EnumGameDirectory.ROOT_FOLDER); - public ImmediateObjectProperty gameDirTypeProperty() { + public ObjectProperty gameDirTypeProperty() { return gameDirTypeProperty; } @@ -434,9 +439,9 @@ public void setGameDirType(EnumGameDirectory gameDirType) { /** * Your custom gameDir */ - private final ImmediateStringProperty gameDirProperty = new ImmediateStringProperty(this, "gameDir", ""); + private final StringProperty gameDirProperty = new SimpleStringProperty(this, "gameDir", ""); - public ImmediateStringProperty gameDirProperty() { + public StringProperty gameDirProperty() { return gameDirProperty; } @@ -455,9 +460,9 @@ public void setGameDir(String gameDir) { * 1 - Hide the launcher when the game starts.
* 2 - Keep the launcher open.
*/ - private final ImmediateObjectProperty launcherVisibilityProperty = new ImmediateObjectProperty<>(this, "launcherVisibility", LauncherVisibility.HIDE); + private final ObjectProperty launcherVisibilityProperty = new SimpleObjectProperty<>(this, "launcherVisibility", LauncherVisibility.HIDE); - public ImmediateObjectProperty launcherVisibilityProperty() { + public ObjectProperty launcherVisibilityProperty() { return launcherVisibilityProperty; } 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 6439af6fa6..66e462d51f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -35,6 +35,7 @@ import org.jackhuang.hmcl.ui.account.AccountList; import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage; import org.jackhuang.hmcl.ui.construct.*; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.decorator.DecoratorController; import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider; import org.jackhuang.hmcl.ui.profile.ProfileList; @@ -223,14 +224,14 @@ public static void dialog(String text) { } public static void dialog(String text, String title) { - dialog(text, title, MessageBox.INFORMATION_MESSAGE); + dialog(text, title, MessageType.INFORMATION); } - public static void dialog(String text, String title, int type) { + public static void dialog(String text, String title, MessageType type) { dialog(text, title, type, null); } - public static void dialog(String text, String title, int type, Runnable onAccept) { + public static void dialog(String text, String title, MessageType type, Runnable onAccept) { dialog(new MessageDialogPane(text, title, type, onAccept)); } 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 901f2837c9..4e3c009483 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -201,11 +201,11 @@ public class LogWindowImpl extends StackPane { if (!flag) cboLines.getSelectionModel().select(0); - btnFatals.textProperty().bind(Bindings.createStringBinding(() -> Integer.toString(fatal.get()) + " fatals", fatal)); - btnErrors.textProperty().bind(Bindings.createStringBinding(() -> Integer.toString(error.get()) + " errors", error)); - btnWarns.textProperty().bind(Bindings.createStringBinding(() -> Integer.toString(warn.get()) + " warns", warn)); - btnInfos.textProperty().bind(Bindings.createStringBinding(() -> Integer.toString(info.get()) + " infos", info)); - btnDebugs.textProperty().bind(Bindings.createStringBinding(() -> Integer.toString(debug.get()) + " debugs", debug)); + btnFatals.textProperty().bind(Bindings.concat(fatal, " fatals")); + btnErrors.textProperty().bind(Bindings.concat(error, " errors")); + btnWarns.textProperty().bind(Bindings.concat(warn, " warns")); + btnInfos.textProperty().bind(Bindings.concat(info, " infos")); + btnDebugs.textProperty().bind(Bindings.concat(debug, " debugs")); btnFatals.selectedProperty().addListener(o -> specificChanged()); btnErrors.selectedProperty().addListener(o -> specificChanged()); 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 7adb5bbc69..68bfddb856 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -31,7 +31,7 @@ import javafx.scene.text.Font; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.*; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.decorator.DecoratorPage; import org.jackhuang.hmcl.upgrade.RemoteVersion; @@ -228,7 +228,7 @@ protected void onExportLogs() { try { Files.write(logFile, Logging.getRawLogs()); } catch (IOException e) { - Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + e, null, MessageBox.ERROR_MESSAGE)); + Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + e, null, MessageType.ERROR)); LOG.log(Level.WARNING, "Failed to export logs", e); return; } 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 deleted file mode 100644 index 88c0e71ab1..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -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.ui.FXUtils; - -import javax.swing.*; -import java.util.Optional; - -import static org.jackhuang.hmcl.util.i18n.I18n.i18n; - -public final class MessageBox { - private MessageBox() { - } - - private static final String TITLE = i18n("message.info"); - - /** - * User Operation: Yes - */ - public static final int YES_OPTION = 0; - - /** - * User Operation: No - */ - public static final int NO_OPTION = 1; - - /** - * User Operation: Cancel - */ - public static final int CANCEL_OPTION = 2; - - /** - * User Operation: OK - */ - public static final int OK_OPTION = 0; - - /** - * User Operation: Closed Message Box - */ - public static final int CLOSED_OPTION = -1; - - /** - * Buttons: Yes No - */ - public static final int YES_NO_OPTION = 10; - /** - * Buttons: Yes No Cancel - */ - public static final int YES_NO_CANCEL_OPTION = 11; - /** - * Buttons: OK Cancel - */ - public static final int OK_CANCEL_OPTION = 12; - - /** - * Message Box Type: Error - */ - public static final int ERROR_MESSAGE = 0; - /** - * Message Box Type: Info - */ - public static final int INFORMATION_MESSAGE = 1; - /** - * Message Box Type: Warning - */ - public static final int WARNING_MESSAGE = 2; - /** - * Message Box Type: Question - */ - public static final int QUESTION_MESSAGE = 3; - /** - * Message Box Type: Fine - */ - public static final int FINE_MESSAGE = 4; - /** - * Message Box Type: Plain - */ - public static final int PLAIN_MESSAGE = -1; - - - public static void show(String message) { - show(message, TITLE); - } - - /** - * Show MsgBox with title and options - * - * @param message The Message - * @param title The title of MsgBox. - * @return user operation. - */ - public static Optional show(String message, String title) { - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle(title); - alert.setHeaderText(title); - alert.setContentText(message); - return alert.showAndWait(); - } - - public static int confirm(String message, String title) { - return confirm(message, title, -1); - } - - public static int confirm(String message, int option) { - return confirm(message, TITLE, option); - } - - public static int confirm(String message, String title, int option) { - 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) { - return input(message, UIManager.getString("OptionPane.inputDialogTitle")); - } - - public static Optional input(String message, String title) { - return input(message, title, ""); - } - - public static Optional input(String message, String title, String initialValue) { - TextInputDialog dialog = new TextInputDialog(initialValue); - dialog.setTitle(title); - dialog.setHeaderText(message); - dialog.setContentText(message); - - return dialog.showAndWait(); - } -} 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 f0b576da84..f39b757d50 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 @@ -32,6 +32,15 @@ public final class MessageDialogPane extends StackPane { + public static enum MessageType { + ERROR, + INFORMATION, + WARNING, + QUESTION, + FINE, + PLAIN, + } + @FXML private JFXButton acceptButton; @FXML @@ -45,7 +54,7 @@ public final class MessageDialogPane extends StackPane { @FXML private HBox actions; - public MessageDialogPane(String text, String title, int type, Runnable onAccept) { + public MessageDialogPane(String text, String title, MessageType type, Runnable onAccept) { FXUtils.loadFXML(this, "/assets/fxml/message-dialog.fxml"); if (title != null) @@ -60,19 +69,19 @@ public MessageDialogPane(String text, String title, int type, Runnable onAccept) actions.getChildren().remove(cancelButton); switch (type) { - case MessageBox.INFORMATION_MESSAGE: + case INFORMATION: graphic.setGraphic(SVG.infoCircle(Theme.blackFillBinding(), 40, 40)); break; - case MessageBox.ERROR_MESSAGE: + case ERROR: graphic.setGraphic(SVG.closeCircle(Theme.blackFillBinding(), 40, 40)); break; - case MessageBox.FINE_MESSAGE: + case FINE: graphic.setGraphic(SVG.checkCircle(Theme.blackFillBinding(), 40, 40)); break; - case MessageBox.WARNING_MESSAGE: + case WARNING: graphic.setGraphic(SVG.alert(Theme.blackFillBinding(), 40, 40)); break; - case MessageBox.QUESTION_MESSAGE: + case QUESTION: graphic.setGraphic(SVG.helpCircle(Theme.blackFillBinding(), 40, 40)); break; default: @@ -81,7 +90,7 @@ public MessageDialogPane(String text, String title, int type, Runnable onAccept) } public MessageDialogPane(String text, String title, Runnable onAccept, Runnable onCancel) { - this(text, title, MessageBox.QUESTION_MESSAGE, onAccept); + this(text, title, MessageType.QUESTION, onAccept); cancelButton.setVisible(true); cancelButton.setOnMouseClicked(e -> { 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 87f1360f5c..b245aac4c4 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 @@ -28,7 +28,7 @@ import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; import org.jackhuang.hmcl.util.StringUtils; @@ -121,11 +121,11 @@ public boolean cancel() { public static void alertFailureMessage(Exception exception, Runnable next) { if (exception instanceof LibraryDownloadException) { - Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); + Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); } else if (exception instanceof DownloadException) { - Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageBox.ERROR_MESSAGE, next); + Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); } else { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); + Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageType.ERROR, next); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index 5536940abf..614055ae72 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -27,7 +27,7 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; @@ -84,11 +84,11 @@ private Task finishModpackInstallingAsync(Map settings) { try { return ModpackHelper.getUpdateTask(profile, selected, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name))); } catch (UnsupportedModpackException e) { - Controllers.dialog(i18n("modpack.unsupported"), i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(i18n("modpack.unsupported"), i18n("message.error"), MessageType.ERROR); } catch (MismatchedModpackTypeException e) { - Controllers.dialog(i18n("modpack.mismatched_type"), i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(i18n("modpack.mismatched_type"), i18n("message.error"), MessageType.ERROR); } catch (IOException e) { - Controllers.dialog(i18n("modpack.invalid"), i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(i18n("modpack.invalid"), i18n("message.error"), MessageType.ERROR); } return null; } else { @@ -105,9 +105,9 @@ public Object finish(Map settings) { public void onFail(Map settings, Exception exception, Runnable next) { if (exception instanceof CurseCompletionException) { if (exception.getCause() instanceof FileNotFoundException) { - Controllers.dialog(i18n("modpack.type.curse.not_found"), i18n("install.failed"), MessageBox.ERROR_MESSAGE, next); + Controllers.dialog(i18n("modpack.type.curse.not_found"), i18n("install.failed"), MessageType.ERROR, next); } else { - Controllers.dialog(i18n("modpack.type.curse.tolerable_error"), i18n("install.success"), MessageBox.INFORMATION_MESSAGE, next); + Controllers.dialog(i18n("modpack.type.curse.tolerable_error"), i18n("install.success"), MessageType.INFORMATION, next); } } else { InstallerWizardProvider.alertFailureMessage(exception, next); 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 4efc6f38b9..82ee5b12b1 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 @@ -33,7 +33,7 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.WebStage; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; @@ -129,7 +129,7 @@ public ModpackPage(WizardController controller) { txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate())); } }, e -> { - Controllers.dialog(i18n("modpack.task.install.error"), i18n("message.error"), MessageBox.ERROR_MESSAGE); + Controllers.dialog(i18n("modpack.task.install.error"), i18n("message.error"), MessageType.ERROR); Platform.runLater(controller::onEnd); }).start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index b5b0b45e7d..dc2fbad098 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -57,7 +57,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; @@ -71,7 +70,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag private Profile profile; private String versionId; private boolean javaItemsLoaded; - private InvalidationListener specificSettingsListener; @FXML private VBox rootPane; @FXML private ScrollPane scroll; @@ -100,6 +98,12 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag @FXML private JFXCheckBox chkEnableSpecificSettings; @FXML private BorderPane settingsTypePane; + private InvalidationListener specificSettingsListener = any -> { + chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal()); + }; + + private InvalidationListener javaListener = any -> initJavaSubtitle(); + public VersionSettingsPage() { FXUtils.loadFXML(this, "/assets/fxml/version/version-settings.fxml"); @@ -148,10 +152,6 @@ private void initialize() { Platform.runLater(() -> loadVersion(profile, versionId)); }); - specificSettingsListener = o -> { - chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal()); - }; - componentList.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not()); advancedSettingsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not()); } @@ -193,6 +193,8 @@ public void loadVersion(Profile profile, String versionId) { FXUtils.unbindEnum(cboLauncherVisibility); lastVersionSetting.usesGlobalProperty().removeListener(specificSettingsListener); + lastVersionSetting.javaDirProperty().removeListener(javaListener); + lastVersionSetting.javaProperty().removeListener(javaListener); gameDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.gameDirTypeProperty()); gameDirItem.subtitleProperty().unbind(); @@ -232,9 +234,8 @@ public void loadVersion(Profile profile, String versionId) { } }); - versionSetting.javaDirProperty().setChangedListener(it -> initJavaSubtitle(versionSetting)); - versionSetting.javaProperty().setChangedListener(it -> initJavaSubtitle(versionSetting)); - initJavaSubtitle(versionSetting); + versionSetting.javaDirProperty().addListener(javaListener); + versionSetting.javaProperty().addListener(javaListener); gameDirItem.selectedDataProperty().bindBidirectional(versionSetting.gameDirTypeProperty()); gameDirItem.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath()).normalize().toString(), @@ -243,6 +244,7 @@ public void loadVersion(Profile profile, String versionId) { lastVersionSetting = versionSetting; initializeSelectedJava(); + initJavaSubtitle(); loadIcon(); } @@ -267,11 +269,14 @@ private void initializeSelectedJava() { } } - private void initJavaSubtitle(VersionSetting versionSetting) { + private void initJavaSubtitle() { + VersionSetting versionSetting = lastVersionSetting; + if (versionSetting == null) + return; Task.of(variables -> variables.set("java", versionSetting.getJavaVersion())) .subscribe(Task.of(Schedulers.javafx(), variables -> javaItem.setSubtitle(variables.getOptional("java") - .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Directory")))); + .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path")))); } @FXML diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 3fde14e655..48fb46f0a4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -24,7 +24,7 @@ import org.jackhuang.hmcl.task.TaskListener; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; -import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.StringUtils; @@ -67,9 +67,9 @@ public void onStop(boolean success, TaskExecutor executor) { pane.fireEvent(new DialogCloseEvent()); if (success) { if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) - Controllers.dialog((String) settings.get("success_message"), null, MessageBox.FINE_MESSAGE, () -> onEnd()); + Controllers.dialog((String) settings.get("success_message"), null, MessageType.FINE, () -> onEnd()); else if (!settings.containsKey("forbid_success_message")) - Controllers.dialog(i18n("message.success"), null, MessageBox.FINE_MESSAGE, () -> onEnd()); + Controllers.dialog(i18n("message.success"), null, MessageType.FINE, () -> onEnd()); } else { if (executor.getLastException() == null) return; @@ -77,9 +77,9 @@ else if (!settings.containsKey("forbid_success_message")) if (settings.get("failure_callback") instanceof WizardProvider.FailureCallback) ((WizardProvider.FailureCallback)settings.get("failure_callback")).onFail(settings, executor.getLastException(), () -> onEnd()); else if (settings.get("failure_message") instanceof String) - Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageBox.ERROR_MESSAGE, () -> onEnd()); + Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageType.ERROR, () -> onEnd()); else if (!settings.containsKey("forbid_failure_message")) - Controllers.dialog(appendix, i18n("wizard.failed"), MessageBox.ERROR_MESSAGE, () -> onEnd()); + Controllers.dialog(appendix, i18n("wizard.failed"), MessageType.ERROR, () -> onEnd()); } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index c97f1cf4af..d2cacc977b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -26,7 +26,7 @@ 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.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.JarUtils; @@ -116,14 +116,14 @@ public static void updateFrom(RemoteVersion version) { System.exit(0); } catch (IOException e) { LOG.log(Level.WARNING, "Failed to update to " + version, e); - Platform.runLater(() -> Controllers.dialog(StringUtils.getStackTrace(e), i18n("update.failed"), MessageBox.ERROR_MESSAGE)); + Platform.runLater(() -> Controllers.dialog(StringUtils.getStackTrace(e), i18n("update.failed"), MessageType.ERROR)); return; } } else { Throwable e = executor.getLastException(); LOG.log(Level.WARNING, "Failed to update to " + version, e); - Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE)); + Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageType.ERROR)); } }); } 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 f5f99e31f7..dc0e90d60f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java @@ -18,9 +18,11 @@ package org.jackhuang.hmcl.util; import javafx.application.Platform; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; + import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.ui.CrashWindow; -import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.upgrade.IntegrityChecker; import org.jackhuang.hmcl.upgrade.UpdateChecker; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -69,7 +71,10 @@ private boolean checkThrowable(Throwable e) { String info = entry.getValue(); LOG.severe(info); try { - MessageBox.show(info); + Alert alert = new Alert(AlertType.INFORMATION, info); + alert.setTitle(i18n("message.info")); + alert.setHeaderText(i18n("message.info")); + alert.showAndWait(); } catch (Throwable t) { LOG.log(Level.SEVERE, "Unable to show message", t); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java index a5363ca1a2..d94f09f358 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java @@ -58,10 +58,6 @@ public final class Locales { public static final List LOCALES = Lang.immutableListOf(DEFAULT, EN, ZH_CN, ZH); - public static SupportedLocale getLocale(int index) { - return Lang.get(LOCALES, index).orElse(DEFAULT); - } - public static SupportedLocale getLocaleByName(String name) { if (name == null) return DEFAULT; switch (name.toLowerCase()) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java index d1031742b8..2cc57b3cb2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java @@ -24,7 +24,6 @@ import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; -import java.io.IOException; /** * This task is to save the version json. @@ -52,8 +51,6 @@ public VersionJsonSaveTask(DefaultGameRepository repository, Version version) { @Override public void execute() throws Exception { File json = repository.getVersionJson(version.getId()).getAbsoluteFile(); - if (!FileUtils.makeFile(json)) - throw new IOException("Cannot create file " + json); FileUtils.writeText(json, JsonUtils.GSON.toJson(version)); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModInfo.java index 290c7f6b3b..b1dd332462 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModInfo.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModInfo.java @@ -20,7 +20,9 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.javafx.ImmediateBooleanProperty; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import java.io.File; import java.io.IOException; @@ -42,7 +44,7 @@ public final class ModInfo implements Comparable { private final String gameVersion; private final String url; private final String fileName; - private final ImmediateBooleanProperty activeProperty; + private final BooleanProperty activeProperty; public ModInfo(ModManager modManager, File file, String name, String description) { this(modManager, file, name, description, "", "", "", ""); @@ -57,7 +59,7 @@ public ModInfo(ModManager modManager, File file, String name, String description this.gameVersion = gameVersion; this.url = url; - activeProperty = new ImmediateBooleanProperty(this, "active", !modManager.isDisabled(file)) { + activeProperty = new SimpleBooleanProperty(this, "active", !modManager.isDisabled(file)) { @Override protected void invalidated() { Path path = ModInfo.this.file.toAbsolutePath(); @@ -104,7 +106,7 @@ public String getUrl() { return url; } - public ImmediateBooleanProperty activeProperty() { + public BooleanProperty activeProperty() { return activeProperty; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index 01e55f007e..ad6b502436 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.util; -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; import java.util.*; @@ -76,13 +75,6 @@ public static T ignoringException(ExceptionalSupplier supplier, T defa } } - public static void ignoringException(ExceptionalRunnable runnable) { - try { - runnable.run(); - } catch (Exception ignore) { - } - } - /** * Cast {@code obj} to V dynamically. * @param obj the object reference to be cast. @@ -98,20 +90,6 @@ public static Optional tryCast(Object obj, Class clazz) { } } - /** - * Get the element at the specific position {@code index} in {@code list}. - * - * @param index the index of element to be return - * @param the type of elements in {@code list} - * @return the element at the specific position, null if index is out of bound. - */ - public static Optional get(List list, int index) { - if (index < 0 || index >= list.size()) - return Optional.empty(); - else - return Optional.ofNullable(list.get(index)); - } - /** * Join two collections into one list. * diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateBooleanProperty.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateBooleanProperty.java deleted file mode 100644 index b73966b1f8..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateBooleanProperty.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.util.javafx; - -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; - -/** - * @author huangyuhui - * @deprecated Use SimpleBooleanProperty instead - */ -@Deprecated -public class ImmediateBooleanProperty extends SimpleBooleanProperty { - - @Override - public void set(boolean newValue) { - super.get(); - super.set(newValue); - } - - @Override - public void bind(ObservableValue newObservable) { - super.get(); - super.bind(newObservable); - } - - @Override - public void unbind() { - super.get(); - super.unbind(); - } - - public ImmediateBooleanProperty(Object bean, String name, boolean initialValue) { - super(bean, name, initialValue); - ChangeListener changeListener = (a, b, newValue) -> { - }; - addListener(changeListener); - } -} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateIntegerProperty.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateIntegerProperty.java deleted file mode 100644 index 682950a136..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateIntegerProperty.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.util.javafx; - -import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; - -/** - * @author huangyuhui - * @deprecated Use SimpleIntegerProperty instead - */ -@Deprecated -public class ImmediateIntegerProperty extends SimpleIntegerProperty { - - @Override - public void set(int newValue) { - super.get(); - super.set(newValue); - } - - @Override - public void bind(ObservableValue newObservable) { - super.get(); - super.bind(newObservable); - } - - @Override - public void unbind() { - super.get(); - super.unbind(); - } - - public ImmediateIntegerProperty(Object bean, String name, int initialValue) { - super(bean, name, initialValue); - ChangeListener changeListener = (a, b, newValue) -> { - }; - addListener(changeListener); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateObjectProperty.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateObjectProperty.java deleted file mode 100644 index ac1a5f856a..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateObjectProperty.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.util.javafx; - -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; - -/** - * @author huangyuhui - * @deprecated Use SimpleObjectProperty instead - */ -@Deprecated -public class ImmediateObjectProperty extends SimpleObjectProperty { - - @Override - public void set(T newValue) { - super.get(); - super.set(newValue); - } - - @Override - public void bind(ObservableValue newObservable) { - super.get(); - super.bind(newObservable); - } - - @Override - public void unbind() { - super.get(); - super.unbind(); - } - - public ImmediateObjectProperty(Object bean, String name, T initialValue) { - super(bean, name, initialValue); - ChangeListener changeListener = (a, b, newValue) -> { - }; - addListener(changeListener); - } -} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateStringProperty.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateStringProperty.java deleted file mode 100644 index 867e6c2163..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ImmediateStringProperty.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.util.javafx; - -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; - -import java.util.Objects; -import java.util.function.Consumer; - -/** - * @author huangyuhui - * @deprecated Use SimpleStringProperty instead - */ -@Deprecated -public class ImmediateStringProperty extends SimpleStringProperty { - - @Override - public void set(String newValue) { - super.get(); - super.set(newValue); - } - - @Override - public void bind(ObservableValue newObservable) { - super.get(); - super.bind(newObservable); - } - - @Override - public void unbind() { - super.get(); - super.unbind(); - } - - private Consumer consumer = null; - private ChangeListener listener = null; - - public void setChangedListener(Consumer consumer) { - this.consumer = Objects.requireNonNull(consumer); - this.listener = null; - } - - public void setChangedListener(ChangeListener listener) { - this.consumer = null; - this.listener = Objects.requireNonNull(listener); - } - - public ImmediateStringProperty(Object bean, String name, String initialValue) { - super(bean, name, initialValue); - ChangeListener changeListener = (a, b, newValue) -> { - if (consumer != null) - consumer.accept(newValue); - if (listener != null) - listener.changed(a, b, newValue); - }; - addListener(changeListener); - } -} From 9f85e4a63b57b2ea1f4cf690655ce41a73bba5ca Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sun, 24 Feb 2019 12:25:19 +0800 Subject: [PATCH 0045/2639] Do not run GameVersion.minecraftVersion on UI thread --- .../jackhuang/hmcl/ui/versions/GameItem.java | 29 ++++++++++++++----- .../java/org/jackhuang/hmcl/util/Lang.java | 11 +++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java index 6ac923ec22..eaa81fa884 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui.versions; +import javafx.application.Platform; import javafx.beans.property.*; import javafx.scene.control.Control; import javafx.scene.control.Skin; @@ -25,11 +26,20 @@ import org.jackhuang.hmcl.game.GameVersion; import org.jackhuang.hmcl.setting.Profile; +import static org.jackhuang.hmcl.util.Lang.handleUncaught; +import static org.jackhuang.hmcl.util.Lang.threadPool; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + public class GameItem extends Control { + + private static final ThreadPoolExecutor POOL_VERSION_RESOLVE = threadPool("VersionResolve", true, 1, 1, TimeUnit.SECONDS); + private final Profile profile; private final String version; private final StringProperty title = new SimpleStringProperty(); @@ -40,16 +50,19 @@ public GameItem(Profile profile, String id) { this.profile = profile; this.version = id; - String game = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(id)).orElse("Unknown"); - - StringBuilder libraries = new StringBuilder(game); - LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(profile.getRepository().getVersion(id)); - analyzer.getForge().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.forge")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)forge", "")))); - analyzer.getLiteLoader().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.liteloader")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)liteloader", "")))); - analyzer.getOptiFine().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.optifine")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)optifine", "")))); + // GameVersion.minecraftVersion() is a time-costing job (up to ~200 ms) + CompletableFuture.supplyAsync(() -> GameVersion.minecraftVersion(profile.getRepository().getVersionJar(id)).orElse("Unknown"), POOL_VERSION_RESOLVE) + .thenAcceptAsync(game -> { + StringBuilder libraries = new StringBuilder(game); + LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(profile.getRepository().getVersion(id)); + analyzer.getForge().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.forge")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)forge", "")))); + analyzer.getLiteLoader().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.liteloader")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)liteloader", "")))); + analyzer.getOptiFine().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.optifine")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)optifine", "")))); + subtitle.set(libraries.toString()); + }, Platform::runLater) + .exceptionally(handleUncaught); title.set(id); - subtitle.set(libraries.toString()); image.set(profile.getRepository().getVersionIconImage(version)); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index ad6b502436..6dc07855d0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.function.Function; /** * @@ -199,6 +200,16 @@ public static T apply(T t, Consumer consumer) { return t; } + /** + * This is a useful function to prevent exceptions being eaten when using CompletableFuture. + * You can write: + * ... .exceptionally(handleUncaught); + */ + public static final Function handleUncaught = e -> { + handleUncaughtException(e); + return null; + }; + public static void handleUncaughtException(Throwable e) { Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); } From 34890f21b36b803c5118f3e1b2ec9df9e2de9723 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sun, 24 Feb 2019 12:29:58 +0800 Subject: [PATCH 0046/2639] Update issue template --- .github/ISSUE_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 260baa90f6..316ccda2c2 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -6,7 +6,7 @@ -我们发现,对于不经常检查邮箱的人来说,GitHub issues 的反馈效率太低,时隔几个小时甚至一天的情况很多。为了改善反馈效率,并将积极为 HMCL 提供问题反馈和建议的人聚集起来,我们希望在这里反馈的人可以在 HMCL 3 用户 QQ 群:219177735 中反馈信息,**而不在 GitHub Issues 中反馈问题**。 +我们发现,对于不经常检查邮箱的人来说,GitHub Issues 的反馈效率太低,时隔几个小时甚至一天的情况很多。为了改善反馈效率,并将积极为 HMCL 提供问题反馈和建议的人聚集起来,我们希望在这里反馈的人可以在 HMCL 3 用户 QQ 群:219177735 中反馈信息,**而不在 GitHub Issues 中反馈问题**。 如果你希望在 QQ 群中反馈问题,也请将下面的信息表填好直接发在群中,加快我们的沟通速度。 @@ -24,5 +24,5 @@ * 对游戏做的修改(是否自行通过安装器安装 Rift 等 API,以及 mod): * 游戏崩溃报告(如果有): * 启动器崩溃报告(如果有): -* 启动器日志文件(在启动器设置中打开日志文件夹并将文件夹内所有文件打包发在这里): -* 问题描述(如何触发问题): \ No newline at end of file +* 启动器日志文件(出现问题后点击启动器设置中的【导出启动器日志】按钮): +* 问题描述(如何触发问题): From ed66b016db06a7ad788dec5be4a28e6259e93c07 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 10:47:44 +0800 Subject: [PATCH 0047/2639] Rename then-series functions --- .../jackhuang/hmcl/game/LauncherHelper.java | 10 +- .../jackhuang/hmcl/game/ModpackHelper.java | 6 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 5 +- .../hmcl/ui/account/AccountLoginPane.java | 2 +- .../hmcl/ui/account/AddAccountPane.java | 2 +- .../account/AddAuthlibInjectorServerPane.java | 2 +- .../ui/download/InstallerWizardProvider.java | 6 +- .../hmcl/ui/download/ModpackPage.java | 4 +- .../VanillaInstallWizardProvider.java | 2 +- .../hmcl/ui/download/VersionsPage.java | 2 +- .../hmcl/ui/versions/ModListPage.java | 2 +- .../hmcl/ui/versions/VersionSettingsPage.java | 4 +- .../hmcl/ui/versions/WorldListPage.java | 6 +- .../download/DefaultDependencyManager.java | 8 +- .../hmcl/download/DefaultGameBuilder.java | 15 +- .../hmcl/mod/MultiMCModpackInstallTask.java | 2 +- .../jackhuang/hmcl/task/FinalizedTask.java | 71 -------- .../java/org/jackhuang/hmcl/task/Task.java | 124 ++++++++++--- .../org/jackhuang/hmcl/task/TaskExecutor.java | 3 +- .../org/jackhuang/hmcl/task/TaskResult.java | 167 ++++++++++++++---- 20 files changed, 275 insertions(+), 168 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.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 c980ee78a5..93e5b34e4b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -141,7 +141,7 @@ private void launch0() { } }) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) - .thenTaskResult(() -> Task.ofResult(i18n("account.methods"), () -> { + .thenCompose(() -> Task.ofResult(i18n("account.methods"), () -> { try { return account.logIn(); } catch (CredentialExpiredException e) { @@ -152,11 +152,11 @@ private void launch0() { return account.playOffline().orElseThrow(() -> e); } })) - .thenResult(Schedulers.javafx(), authInfo -> { + .thenApply(Schedulers.javafx(), authInfo -> { emitStatus(LoadingState.LAUNCHING); return authInfo; }) - .thenResult(authInfo -> new HMCLGameLauncher( + .thenApply(authInfo -> new HMCLGameLauncher( repository, selectedVersion, authInfo, @@ -165,7 +165,7 @@ private void launch0() { ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. : new HMCLProcessListener(authInfo, setting, gameVersion.isPresent()) )) - .thenTaskResult(launcher -> { // launcher is prev task's result + .thenCompose(launcher -> { // launcher is prev task's result if (scriptFile == null) { return new LaunchTask<>(launcher::launch).setName(i18n("version.launch")); } else { @@ -175,7 +175,7 @@ private void launch0() { }).setName(i18n("version.launch_script")); } }) - .thenVoid(process -> { // process is LaunchTask's result + .thenAccept(process -> { // process is LaunchTask's result if (scriptFile == null) { PROCESSES.add(process); if (launcherVisibility == LauncherVisibility.CLOSE) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index c4bfdac61d..3b256d0442 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -110,13 +110,13 @@ public static Task getInstallTask(Profile profile, File zipFile, String name, Mo if (modpack.getManifest() instanceof CurseManifest) return new CurseInstallTask(profile.getDependency(), zipFile, modpack, ((CurseManifest) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), success, failure); + .whenComplete(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof HMCLModpackManifest) return new HMCLModpackInstallTask(profile, zipFile, modpack, name) - .finalized(Schedulers.defaultScheduler(), success, failure); + .whenComplete(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), success, failure) + .whenComplete(Schedulers.defaultScheduler(), success, failure) .then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); else throw new IllegalStateException("Unrecognized modpack: " + modpack); } 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 0479f27d03..ad0160dee6 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,6 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent; import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.game.ModpackHelper; -import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; @@ -120,8 +119,8 @@ private void onRefreshedVersions(HMCLGameRepository repository) { File modpackFile = new File("modpack.zip").getAbsoluteFile(); if (modpackFile.exists()) { Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) - .thenResult(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) - .thenVoid(modpack -> { + .thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) + .thenAccept(modpack -> { AtomicReference region = new AtomicReference<>(); TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) .with(Task.of(Schedulers.javafx(), this::checkAccount)).executor(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java index 01b6ae5523..00646b113f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java @@ -62,7 +62,7 @@ private void onAccept() { progressBar.setVisible(true); lblCreationWarning.setText(""); Task.ofResult(() -> oldAccount.logInWithPassword(password)) - .finalized(Schedulers.javafx(), authInfo -> { + .whenComplete(Schedulers.javafx(), authInfo -> { success.accept(authInfo); fireEvent(new DialogCloseEvent()); progressBar.setVisible(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 32c76b49f1..579548f804 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -196,7 +196,7 @@ private void onCreationAccept() { Object additionalData = getAuthAdditionalData(); Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData)) - .finalized(Schedulers.javafx(), account -> { + .whenComplete(Schedulers.javafx(), account -> { int oldIndex = Accounts.getAccounts().indexOf(account); if (oldIndex == -1) { Accounts.getAccounts().add(account); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 85ec12ba13..18b3b29703 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ private void onAddNext() { Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).finalized(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); 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 fe5f651c5a..6f826a1a95 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 @@ -93,13 +93,13 @@ public Object finish(Map settings) { TaskResult ret = Task.ofResult(() -> version); if (settings.containsKey("forge")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); if (settings.containsKey("liteloader")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); if (settings.containsKey("optifine")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); return ret.then(profile.getRepository().refreshVersionsAsync()); } 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 0149028f20..7a762498b8 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 @@ -110,8 +110,8 @@ public ModpackPage(WizardController controller) { spinnerPane.showSpinner(); Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath())) - .thenResult(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) - .finalized(Schedulers.javafx(), manifest -> { + .thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) + .whenComplete(Schedulers.javafx(), manifest -> { spinnerPane.hideSpinner(); controller.getSettings().put(MODPACK_MANIFEST, manifest); lblName.setText(manifest.getName()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 9a3e6bcbfb..e64696b2c4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ private Task finishVersionDownloadingAsync(Map settings) { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions()) .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); } 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 1787606c33..dfe82d5d49 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 @@ -128,7 +128,7 @@ private List loadVersions() { @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((isDependentsSucceeded, exception) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index c420c5d5d7..39e3d269e2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -91,7 +91,7 @@ public void loadMods(ModManager modManager) { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).finalized(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index be654a339f..17619e040d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -118,7 +118,7 @@ private void initialize() { FXUtils.smoothScrolling(scroll); - Task.ofResult(JavaVersion::getJavas).thenVoid(Schedulers.javafx(), list -> { + Task.ofResult(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> { javaItem.loadChildren(list.stream() .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) @@ -274,7 +274,7 @@ private void initJavaSubtitle() { if (versionSetting == null) return; Task.ofResult(versionSetting::getJavaVersion) - .thenVoid(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) + .thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path"))) .start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 195da3bd74..cf7b62a8fd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -51,7 +51,7 @@ public void loadVersion(Profile profile, String id) { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .finalized(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { + .whenComplete(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); @@ -73,10 +73,10 @@ private void installWorld(File zipFile) { // Only accept one world file because user is required to confirm the new world name // Or too many input dialogs are popped. Task.ofResult(() -> new World(zipFile.toPath())) - .finalized(Schedulers.javafx(), world -> { + .whenComplete(Schedulers.javafx(), world -> { Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { Task.of(() -> world.install(savesDir, name)) - .finalized(Schedulers.javafx(), () -> { + .whenComplete(Schedulers.javafx(), () -> { itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); resolve.run(); }, e -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index c094c719c0..ac656d9fc2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -91,7 +91,7 @@ public Task checkLibraryCompletionAsync(Version version) { public TaskResult installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); return versionList.loadAsync(gameVersion, getDownloadProvider()) - .thenTaskResult(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) + .thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) .orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion)))); } @@ -107,9 +107,9 @@ else if (libraryVersion instanceof OptiFineRemoteVersion) else throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized."); return task - .thenTaskResult(LibrariesUniqueTask::new) - .thenTaskResult(MaintainTask::new) - .thenTaskResult(newVersion -> new VersionJsonSaveTask(repository, newVersion)); + .thenCompose(LibrariesUniqueTask::new) + .thenCompose(MaintainTask::new) + .thenCompose(newVersion -> new VersionJsonSaveTask(repository, newVersion)); } 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 885517422e..4791266f75 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskResult; -import org.jackhuang.hmcl.util.AutoTypingMap; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -50,7 +49,7 @@ public DownloadProvider getDownloadProvider() { @Override public Task buildAsync() { - return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenTaskResult(rawJson -> { + return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> { Version original = JsonUtils.GSON.fromJson(rawJson, Version.class); Version version = original.setId(name).setJar(null); Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask( @@ -58,20 +57,20 @@ public Task buildAsync() { new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. - TaskResult libraryTask = vanillaTask.thenResult(() -> version); + TaskResult libraryTask = vanillaTask.thenSupply(() -> version); if (toolVersions.containsKey("forge")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "forge")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge")); if (toolVersions.containsKey("liteloader")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "liteloader")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "liteloader")); if (toolVersions.containsKey("optifine")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "optifine")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "optifine")); for (RemoteVersion remoteVersion : remoteVersions) - libraryTask = libraryTask.thenTaskResult(dependencyManager.installLibraryAsync(remoteVersion)); + libraryTask = libraryTask.thenCompose(dependencyManager.installLibraryAsync(remoteVersion)); return libraryTask; - }).finalized((isDependentsSucceeded, exception) -> { + }).whenComplete((isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); 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 c453ce8591..6095604ecd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -156,7 +156,7 @@ public void execute() throws Exception { } } - dependencies.add(new MaintainTask(version).thenTaskResult(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion))); + dependencies.add(new MaintainTask(version).thenCompose(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion))); dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name))); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java deleted file mode 100644 index a060d0d7c1..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import java.util.Collection; -import java.util.Collections; - -/** - * A task that combines two tasks and make sure [pred] runs before succ. - * - * @author huangyuhui - */ -final class FinalizedTask extends Task { - - private final Task pred; - private final FinalizedCallback callback; - private final Scheduler scheduler; - - /** - * A task that combines two tasks and make sure pred runs before succ. - * - * @param pred the task that runs before succ. - * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. - */ - public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback) { - this.pred = pred; - this.scheduler = scheduler; - this.callback = callback; - - setSignificance(TaskSignificance.MODERATE); - } - - @Override - public Scheduler getScheduler() { - return scheduler; - } - - @Override - public void execute() throws Exception { - callback.execute(isDependentsSucceeded(), pred.getLastException()); - - if (!isDependentsSucceeded()) - throw new SilentException(); - } - - @Override - public Collection getDependents() { - return Collections.singleton(pred); - } - - @Override - public boolean isRelyingOnDependents() { - return false; - } -} - 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 cede8eebc7..3f7d3204b3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -265,18 +265,6 @@ public final boolean test() { return executor().test(); } - public final void subscribe(Task subscriber) { - new TaskExecutor(then(subscriber)).start(); - } - - public final void subscribe(Scheduler scheduler, ExceptionalRunnable closure) { - subscribe(of(scheduler, closure)); - } - - public final void subscribe(ExceptionalRunnable closure) { - subscribe(of(closure)); - } - public final Task then(Task b) { return then(convert(b)); } @@ -285,13 +273,29 @@ public final Task then(ExceptionalSupplier b) { return new CoupleTask(this, b, true); } - public final TaskResult thenResult(Callable supplier) { - return thenTaskResult(() -> Task.ofResult(supplier)); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the default Scheduler. + * + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public final TaskResult thenSupply(Callable fn) { + return thenCompose(() -> Task.ofResult(fn)); } - public final TaskResult thenTaskResult(ExceptionalSupplier, ?> taskSupplier) { - return new TaskResult() { - TaskResult then; + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed. + * + * @param fn the function returning a new TaskResult + * @param the type of the returned TaskResult's result + * @return the TaskResult + */ + public final TaskResult thenCompose(ExceptionalSupplier, ?> fn) { + return new TaskResult() { + TaskResult then; @Override public Collection getDependents() { @@ -300,7 +304,7 @@ public Collection getDependents() { @Override public void execute() throws Exception { - then = taskSupplier.get().storeTo(this::setResult); + then = fn.get().storeTo(this::setResult); } @Override @@ -318,17 +322,87 @@ public final Task with(ExceptionalSupplier b) { return new CoupleTask(this, b, false); } - public final Task finalized(FinalizedCallback b) { - return finalized(Schedulers.defaultScheduler(), b); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked, a boolean + * value represents the execution status of this task, and the exception + * (or {@code null} if none) of this task as arguments. The returned task + * is completed when the action returns. If the supplied action itself + * encounters an exception, then the returned task exceptionally completes + * with this exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @return the new Task + */ + public final Task whenComplete(FinalizedCallback action) { + return whenComplete(Schedulers.defaultScheduler(), action); } - public final Task finalized(Scheduler scheduler, FinalizedCallback b) { - return new FinalizedTask(this, scheduler, b).setName(getCaller()); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked, a boolean + * value represents the execution status of this task, and the exception + * (or {@code null} if none) of this task as arguments. The returned task + * is completed when the action returns. If the supplied action itself + * encounters an exception, then the returned task exceptionally completes + * with this exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + return new Task() { + { + setSignificance(TaskSignificance.MODERATE); + } + + @Override + public Scheduler getScheduler() { + return scheduler; + } + + @Override + public void execute() throws Exception { + action.execute(isDependentsSucceeded(), Task.this.getLastException()); + + if (!isDependentsSucceeded()) + throw new SilentException(); + } + + @Override + public Collection getDependents() { + return Collections.singleton(Task.this); + } + + @Override + public boolean isRelyingOnDependents() { + return false; + } + }.setName(getCaller()); } - // T, K here is necessary, or javac cannot infer type of failure - public final Task finalized(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { - return finalized(scheduler, (isDependentsSucceeded, exception) -> { + /** + * Returns a new Task with the same exception as this task, that executes + * the given actions when this task completes. + * + *

When this task is complete, the given success action is invoked, the + * given failure action is invoked with the exception of this task. The + * returned task is completed when the action returns. If the supplied + * action itself encounters an exception, then the returned task exceptionally + * completes with this exception unless this task also + * completed exceptionally. + * + * @param success the action to perform when this task successfully completed + * @param failure the action to perform when this task exceptionally returned + * @return the new Task + */ + public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { + return whenComplete(scheduler, (isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { if (success != null) try { 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 12587b7158..82d48f36b7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -133,6 +133,7 @@ private boolean executeTasks(Collection tasks) throws Interrupte private boolean executeTask(Task task) { if (canceled) { task.setState(Task.TaskState.FAILED); + task.setLastException(new CancellationException()); return false; } @@ -221,7 +222,7 @@ private boolean executeTask(Task task) { task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); } catch (SilentException | RejectedExecutionException e) { - // do nothing + task.setLastException(e); } catch (Exception e) { task.setLastException(e); lastException = e; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index 5f9185ae0e..342a1ab2e6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -29,35 +29,55 @@ * * @author huangyuhui */ -public abstract class TaskResult extends Task { +public abstract class TaskResult extends Task { - private V result; - private Consumer resultConsumer; + private T result; + private Consumer resultConsumer; @Override - public TaskResult setName(String name) { + public TaskResult setName(String name) { super.setName(name); return this; } - public V getResult() { + /** + * Returns the result of this task. + * + * The result will be generated only if the execution is completed. + */ + public T getResult() { return result; } - public void setResult(V result) { + protected void setResult(T result) { this.result = result; if (resultConsumer != null) resultConsumer.accept(result); } - public TaskResult storeTo(Consumer resultConsumer) { - this.resultConsumer = resultConsumer; + /** + * Sync the result of this task by given action. + * + * @param action the action to perform when result of this task changed + * @return this TaskResult + */ + public TaskResult storeTo(Consumer action) { + this.resultConsumer = action; return this; } - public TaskResult thenTaskResult(ExceptionalFunction, E> taskSupplier) { - return new TaskResult() { - TaskResult then; + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed with result of this task as the argument + * to the supplied function. + * + * @param fn the function returning a new TaskResult + * @param the type of the returned TaskResult's result + * @return the TaskResult + */ + public TaskResult thenCompose(ExceptionalFunction, E> fn) { + return new TaskResult() { + TaskResult then; @Override public Collection getDependents() { @@ -66,7 +86,7 @@ public Collection getDependents() { @Override public void execute() throws Exception { - then = taskSupplier.apply(TaskResult.this.getResult()).storeTo(this::setResult); + then = fn.apply(TaskResult.this.getResult()).storeTo(this::setResult); } @Override @@ -76,44 +96,129 @@ public Collection getDependencies() { }; } - public Task then(ExceptionalFunction taskSupplier) { - return new CoupleTask(this, () -> taskSupplier.apply(getResult()), true); + /** + * Returns a new Task that, when this task completes + * normally, is executed with this task as the argument + * to the supplied function. + * + * @param fn the function returning a new Task + * @return the Task + */ + public Task then(ExceptionalFunction fn) { + return new CoupleTask(this, () -> fn.apply(getResult()), true); } - public TaskResult thenResult(ExceptionalFunction task) { - return thenResult(Schedulers.defaultScheduler(), task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(ExceptionalFunction fn) { + return thenApply(Schedulers.defaultScheduler(), fn); } - public TaskResult thenResult(Scheduler scheduler, ExceptionalFunction task) { - return thenResult(getCaller(), scheduler, task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(Scheduler scheduler, ExceptionalFunction fn) { + return thenApply(getCaller(), scheduler, fn); } - public TaskResult thenResult(String name, Scheduler scheduler, ExceptionalFunction task) { - return new Subtask<>(name, scheduler, task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param name the name of this new TaskResult for displaying + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(String name, Scheduler scheduler, ExceptionalFunction fn) { + return new Subtask<>(name, scheduler, fn); } - // stupid javac stop us from renaming thenVoid to thenResult - public Task thenVoid(ExceptionalConsumer task) { - return thenVoid(Schedulers.defaultScheduler(), task); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the + * returned Task + * @return the new Task + */ + public Task thenAccept(ExceptionalConsumer action) { + return thenAccept(Schedulers.defaultScheduler(), action); } - public Task thenVoid(Scheduler scheduler, ExceptionalConsumer task) { - return new CoupleTask(this, () -> Task.of(scheduler, () -> task.accept(getResult())), true); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenAccept(Scheduler scheduler, ExceptionalConsumer action) { + return new CoupleTask(this, () -> Task.of(scheduler, () -> action.accept(getResult())), true); } - public Task finalized(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { - return finalized(scheduler, () -> success.accept(getResult()), failure); + /** + * Returns a new Task with the same exception as this task, that executes + * the given actions when this task completes. + * + *

When this task is complete, the given success action is invoked with + * the result, the given failure action is invoked with the exception of + * this task. The returned task is completed when the action returns. If + * the supplied action itself encounters an exception, then the returned + * task exceptionally completes with this exception unless this task also + * completed exceptionally. + * + * @param success the action to perform when this task successfully completed + * @param failure the action to perform when this task exceptionally returned + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { + return whenComplete(scheduler, () -> success.accept(getResult()), failure); } - public Task finalized(Scheduler scheduler, FinalizedCallback callback) { - return finalized(scheduler, ((isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception))); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked with the + * result (or {@code null} if none), a boolean value represents the + * execution status of this task, and the exception (or {@code null} + * if none) of this task as arguments. The returned task is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned task exceptionally completes with this + * exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + return whenComplete(scheduler, ((isDependentsSucceeded, exception) -> action.execute(getResult(), isDependentsSucceeded, exception))); } private class Subtask extends TaskResult { private final Scheduler scheduler; - private final ExceptionalFunction callable; + private final ExceptionalFunction callable; - public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { + public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { this.scheduler = scheduler; this.callable = callable; From b22e724a3f07266709d11235a726e187ea3a5dbb Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 11:35:52 +0800 Subject: [PATCH 0048/2639] Remove SilentException --- .../jackhuang/hmcl/ui/DialogController.java | 7 +++-- .../hmcl/ui/account/AccountListItem.java | 3 ++ .../jackhuang/hmcl/mod/ModpackUpdateTask.java | 8 ------ .../jackhuang/hmcl/task/SilentException.java | 28 ------------------- .../java/org/jackhuang/hmcl/task/Task.java | 17 +++++++++-- .../org/jackhuang/hmcl/task/TaskExecutor.java | 18 ++++++------ 6 files changed, 32 insertions(+), 49 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/SilentException.java 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 ff6ecf94bc..e2bcd98d25 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java @@ -20,17 +20,18 @@ import com.jfoenix.utils.JFXUtilities; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; +import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; -import org.jackhuang.hmcl.task.SilentException; import org.jackhuang.hmcl.ui.account.AccountLoginPane; import java.util.Optional; +import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; public final class DialogController { - public static AuthInfo logIn(Account account) throws Exception { + public static AuthInfo logIn(Account account) throws CancellationException, AuthenticationException, InterruptedException { if (account instanceof YggdrasilAccount) { CountDownLatch latch = new CountDownLatch(1); AtomicReference res = new AtomicReference<>(null); @@ -42,7 +43,7 @@ public static AuthInfo logIn(Account account) throws Exception { Controllers.dialog(pane); }); latch.await(); - return Optional.ofNullable(res.get()).orElseThrow(SilentException::new); + return Optional.ofNullable(res.get()).orElseThrow(CancellationException::new); } return account.logIn(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java index 1d1e92fefa..656bf87d56 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java @@ -37,6 +37,7 @@ import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import java.util.concurrent.CancellationException; import java.util.logging.Level; public class AccountListItem extends RadioButton { @@ -84,6 +85,8 @@ public void refresh() { } catch (CredentialExpiredException e) { try { DialogController.logIn(account); + } catch (CancellationException e1) { + // ignore cancellation } catch (Exception e1) { LOG.log(Level.WARNING, "Failed to refresh " + account + " with password", e1); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java index 54368f6ccb..7adc8754dd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod; import org.jackhuang.hmcl.game.DefaultGameRepository; -import org.jackhuang.hmcl.task.SilentException; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.io.FileUtils; @@ -49,11 +48,6 @@ public ModpackUpdateTask(DefaultGameRepository repository, String id, Task updat } } - @Override - public boolean isRelyingOnDependencies() { - return false; - } - @Override public Collection getDependencies() { return Collections.singleton(updateTask); @@ -78,8 +72,6 @@ public void postExecute() throws Exception { repository.removeVersionFromDisk(id); FileUtils.copyDirectory(backupFolder, repository.getVersionRoot(id).toPath()); - - throw new SilentException(); } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SilentException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SilentException.java deleted file mode 100644 index be6a5266af..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SilentException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -/** - * If a task throws {@link SilentException}, - * the task will be marked as failure but do not log the stacktrace. - * - * @author huangyuhui - */ -public final class SilentException extends Exception { - -} 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 3f7d3204b3..31bb6a5c2f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -33,6 +33,7 @@ import java.util.Collection; import java.util.Collections; import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; import java.util.logging.Level; /** @@ -154,8 +155,15 @@ public boolean doPostExecute() { } /** + * This method will be called after dependency tasks terminated all together. + * + * You can check whether dependencies succeed in this method by calling + * {@link Task#isDependenciesSucceeded()} no matter when + * {@link Task#isRelyingOnDependencies()} returns true or false. + * * @throws InterruptedException if current thread is interrupted * @see Thread#isInterrupted + * @see Task#isDependenciesSucceeded() */ public void postExecute() throws Exception {} @@ -370,8 +378,13 @@ public Scheduler getScheduler() { public void execute() throws Exception { action.execute(isDependentsSucceeded(), Task.this.getLastException()); - if (!isDependentsSucceeded()) - throw new SilentException(); + if (!isDependentsSucceeded()) { + setSignificance(TaskSignificance.MINOR); + if (Task.this.getLastException() == null) + throw new CancellationException(); + else + throw Task.this.getLastException(); + } } @Override 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 82d48f36b7..3cbf487af6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -163,7 +163,7 @@ private boolean executeTask(Task task) { Exception dependentsException = dependents.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) { task.setLastException(dependentsException); - throw new SilentException(); + throw new CancellationException(); } if (doDependentsSucceeded) @@ -187,11 +187,6 @@ private boolean executeTask(Task task) { Collection dependencies = task.getDependencies(); boolean doDependenciesSucceeded = executeTasks(dependencies); Exception dependenciesException = dependencies.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); - if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { - Logging.LOG.severe("Subtasks failed for " + task.getName()); - task.setLastException(dependenciesException); - throw new SilentException(); - } if (doDependenciesSucceeded) task.setDependenciesSucceeded(); @@ -207,6 +202,12 @@ private boolean executeTask(Task task) { } } + if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { + Logging.LOG.severe("Subtasks failed for " + task.getName()); + task.setLastException(dependenciesException); + throw new CancellationException(); + } + flag = true; if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); @@ -221,8 +222,9 @@ private boolean executeTask(Task task) { } task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); - } catch (SilentException | RejectedExecutionException e) { - task.setLastException(e); + } catch (CancellationException | RejectedExecutionException e) { + if (task.getLastException() == null) + task.setLastException(e); } catch (Exception e) { task.setLastException(e); lastException = e; From 8007f1958e0a96ff74cfb541e2cd5015b8cf6d86 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 17:00:17 +0800 Subject: [PATCH 0049/2639] Rename isDependentsSucceeded to isDependentSucceeded --- .../hmcl/ui/account/AddAuthlibInjectorServerPane.java | 2 +- .../org/jackhuang/hmcl/ui/download/VersionsPage.java | 2 +- .../java/org/jackhuang/hmcl/ui/versions/ModListPage.java | 2 +- .../org/jackhuang/hmcl/ui/versions/WorldListPage.java | 2 +- .../org/jackhuang/hmcl/download/DefaultGameBuilder.java | 4 ++-- HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java | 9 +++++---- .../main/java/org/jackhuang/hmcl/task/TaskResult.java | 4 ++-- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 18b3b29703..8f6b0100db 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ private void onAddNext() { Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).whenComplete(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (isDependentSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); 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 dfe82d5d49..5ba8cff00a 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 @@ -128,7 +128,7 @@ private List loadVersions() { @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentsSucceeded, exception) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 39e3d269e2..a7542c3306 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -91,7 +91,7 @@ public void loadMods(ModManager modManager) { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).whenComplete(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (list, isDependentSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index cf7b62a8fd..3dd32f6bb7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -51,7 +51,7 @@ public void loadVersion(Profile profile, String id) { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .whenComplete(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { + .whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); 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 4791266f75..60b8f01d6d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -70,8 +70,8 @@ public Task buildAsync() { libraryTask = libraryTask.thenCompose(dependencyManager.installLibraryAsync(remoteVersion)); return libraryTask; - }).whenComplete((isDependentsSucceeded, exception) -> { - if (!isDependentsSucceeded) + }).whenComplete((isDependentSucceeded, exception) -> { + if (!isDependentSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); } 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 31bb6a5c2f..358184f8a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -354,7 +354,8 @@ public final Task whenComplete(FinalizedCallback action) { * *

When this task is complete, the given action is invoked, a boolean * value represents the execution status of this task, and the exception - * (or {@code null} if none) of this task as arguments. The returned task + * (or {@code null} if none, which means when isDependentSucceeded is false, + * exception may be null) of this task as arguments. The returned task * is completed when the action returns. If the supplied action itself * encounters an exception, then the returned task exceptionally completes * with this exception unless this task also completed exceptionally. @@ -415,8 +416,8 @@ public boolean isRelyingOnDependents() { * @return the new Task */ public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { - return whenComplete(scheduler, (isDependentsSucceeded, exception) -> { - if (isDependentsSucceeded) { + return whenComplete(scheduler, (isDependentSucceeded, exception) -> { + if (isDependentSucceeded) { if (success != null) try { success.run(); @@ -497,7 +498,7 @@ public enum TaskState { } public interface FinalizedCallback { - void execute(boolean isDependentsSucceeded, Exception exception) throws Exception; + void execute(boolean isDependentSucceeded, Exception exception) throws Exception; } static String getCaller() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index 342a1ab2e6..cc8a3485c9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -211,7 +211,7 @@ public Task whenComplete(Scheduler * @return the new Task */ public Task whenComplete(Scheduler scheduler, FinalizedCallback action) { - return whenComplete(scheduler, ((isDependentsSucceeded, exception) -> action.execute(getResult(), isDependentsSucceeded, exception))); + return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception))); } private class Subtask extends TaskResult { @@ -242,6 +242,6 @@ public void execute() throws Exception { } public interface FinalizedCallback { - void execute(V result, boolean isDependentsSucceeded, Exception exception) throws Exception; + void execute(V result, boolean isDependentSucceeded, Exception exception) throws Exception; } } From def45cc3e436590809ed6aefda8edece49b8f0ad Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 23:11:09 +0800 Subject: [PATCH 0050/2639] Fix NumberFormatException when parsing forge version list json --- .../hmcl/download/forge/ForgeBMCLVersionList.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index fca99043eb..b412c09ff6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -60,7 +60,7 @@ public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) final GetTask task = new GetTask(NetworkUtils.toURL("https://bmclapi2.bangbang93.com/forge/minecraft/" + gameVersion)); return new Task() { @Override - public Collection getDependents() { + public Collection getDependents() { return Collections.singleton(task); } @@ -104,7 +104,6 @@ public static final class ForgeVersion implements Validation { private final String branch; private final String mcversion; private final String version; - private final int build; private final List files; /** @@ -112,14 +111,13 @@ public static final class ForgeVersion implements Validation { */ @SuppressWarnings("unused") public ForgeVersion() { - this(null, null, null, 0, null); + this(null, null, null, null); } - public ForgeVersion(String branch, String mcversion, String version, int build, List files) { + public ForgeVersion(String branch, String mcversion, String version, List files) { this.branch = branch; this.mcversion = mcversion; this.version = version; - this.build = build; this.files = files; } @@ -135,10 +133,6 @@ public String getVersion() { return version; } - public int getBuild() { - return build; - } - public List getFiles() { return files; } From dc1df982774299f1248ec8909ba209e5d5f2ea99 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 23:13:31 +0800 Subject: [PATCH 0051/2639] Fix compilation error --- .../jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java | 2 +- .../main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java | 2 +- .../main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java | 2 +- .../main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 8f6b0100db..dcb2214c5f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -110,7 +110,7 @@ private void onAddNext() { addServerPane.setDisable(false); nextPane.hideSpinner(); - if (isDependentsSucceeded) { + if (isDependentSucceeded) { lblServerName.setText(serverBeingAdded.getName()); lblServerUrl.setText(serverBeingAdded.getUrl()); 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 5ba8cff00a..b23af41de2 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 @@ -129,7 +129,7 @@ private List loadVersions() { public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentSucceeded, exception) -> { - if (isDependentsSucceeded) { + if (isDependentSucceeded) { List items = loadVersions(); Platform.runLater(() -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index a7542c3306..62a4da7211 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -93,7 +93,7 @@ public void loadMods(ModManager modManager) { } }).whenComplete(Schedulers.javafx(), (list, isDependentSucceeded, exception) -> { loadingProperty().set(false); - if (isDependentsSucceeded) + if (isDependentSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { if (newValue != null && newValue.getUserData() == ModListPage.this) itemsProperty().setAll(list.stream().map(ModListPageSkin.ModInfoObject::new).collect(Collectors.toList())); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 3dd32f6bb7..53095e6d07 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -53,7 +53,7 @@ public void loadVersion(Profile profile, String id) { Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) .whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> { setLoading(false); - if (isDependentsSucceeded) + if (isDependentSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); }).start(); } From 8f2a1030bc0f4064cce33cf8486128ae4213cd6f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 23:09:17 +0800 Subject: [PATCH 0052/2639] Refactor Task --- .../hmcl/game/HMCLModpackExportTask.java | 2 +- .../hmcl/game/HMCLModpackInstallTask.java | 10 +- .../jackhuang/hmcl/game/LauncherHelper.java | 18 +- .../jackhuang/hmcl/game/ModpackHelper.java | 6 +- .../MultiMCInstallVersionSettingTask.java | 2 +- .../org/jackhuang/hmcl/ui/Controllers.java | 2 +- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 2 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 4 +- .../hmcl/ui/account/AccountLoginPane.java | 2 +- .../hmcl/ui/account/AddAccountPane.java | 2 +- .../account/AddAuthlibInjectorServerPane.java | 2 +- .../hmcl/ui/construct/TaskListPane.java | 12 +- .../ui/download/InstallerWizardProvider.java | 5 +- .../ModpackInstallWizardProvider.java | 4 +- .../hmcl/ui/download/ModpackPage.java | 2 +- .../VanillaInstallWizardProvider.java | 4 +- .../hmcl/ui/export/ExportWizardProvider.java | 10 +- .../hmcl/ui/versions/InstallerListPage.java | 6 +- .../hmcl/ui/versions/ModListPage.java | 8 +- .../hmcl/ui/versions/VersionSettingsPage.java | 4 +- .../hmcl/ui/versions/WorldExportPage.java | 2 +- .../hmcl/ui/versions/WorldListPage.java | 6 +- .../ui/wizard/AbstractWizardDisplayer.java | 4 +- .../TaskExecutorDialogWizardDisplayer.java | 2 +- .../hmcl/ui/wizard/WizardController.java | 2 +- .../hmcl/ui/wizard/WizardDisplayer.java | 2 +- .../jackhuang/hmcl/upgrade/UpdateHandler.java | 2 +- .../download/DefaultDependencyManager.java | 18 +- .../hmcl/download/DefaultGameBuilder.java | 14 +- .../hmcl/download/DependencyManager.java | 8 +- .../jackhuang/hmcl/download/GameBuilder.java | 2 +- .../jackhuang/hmcl/download/MaintainTask.java | 4 +- .../jackhuang/hmcl/download/VersionList.java | 12 +- .../download/forge/ForgeBMCLVersionList.java | 10 +- .../hmcl/download/forge/ForgeInstallTask.java | 16 +- .../download/forge/ForgeNewInstallTask.java | 13 +- .../download/forge/ForgeOldInstallTask.java | 9 +- .../hmcl/download/forge/ForgeVersionList.java | 6 +- .../download/game/GameAssetDownloadTask.java | 10 +- .../game/GameAssetIndexDownloadTask.java | 7 +- .../hmcl/download/game/GameDownloadTask.java | 7 +- .../hmcl/download/game/GameLibrariesTask.java | 6 +- .../hmcl/download/game/GameVersionList.java | 6 +- .../download/game/LibrariesUniqueTask.java | 4 +- .../download/game/LibraryDownloadTask.java | 4 +- .../game/VersionJsonDownloadTask.java | 11 +- .../download/game/VersionJsonSaveTask.java | 4 +- .../liteloader/LiteLoaderBMCLVersionList.java | 7 +- .../liteloader/LiteLoaderInstallTask.java | 11 +- .../liteloader/LiteLoaderVersionList.java | 7 +- .../optifine/OptiFineBMCLVersionList.java | 6 +- .../optifine/OptiFineInstallTask.java | 11 +- .../jackhuang/hmcl/game/GameRepository.java | 4 +- .../hmcl/mod/CurseCompletionTask.java | 12 +- .../jackhuang/hmcl/mod/CurseInstallTask.java | 10 +- .../hmcl/mod/MinecraftInstanceTask.java | 2 +- .../hmcl/mod/ModpackInstallTask.java | 2 +- .../jackhuang/hmcl/mod/ModpackUpdateTask.java | 8 +- .../hmcl/mod/MultiMCModpackInstallTask.java | 10 +- .../org/jackhuang/hmcl/task/CoupleTask.java | 74 --- .../jackhuang/hmcl/task/FileDownloadTask.java | 2 +- .../java/org/jackhuang/hmcl/task/GetTask.java | 23 +- .../org/jackhuang/hmcl/task/ParallelTask.java | 57 -- .../org/jackhuang/hmcl/task/SimpleTask.java | 52 -- .../jackhuang/hmcl/task/SimpleTaskResult.java | 46 -- .../java/org/jackhuang/hmcl/task/Task.java | 554 +++++++++++++++--- .../org/jackhuang/hmcl/task/TaskEvent.java | 6 +- .../org/jackhuang/hmcl/task/TaskExecutor.java | 281 ++++----- .../org/jackhuang/hmcl/task/TaskListener.java | 8 +- .../org/jackhuang/hmcl/task/TaskResult.java | 247 -------- .../util/function/ExceptionalRunnable.java | 6 +- .../org/jackhuang/hmcl/util/TaskTest.java | 18 + 72 files changed, 834 insertions(+), 928 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java create mode 100644 HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java index 3b01f30a0e..c125930341 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java @@ -30,7 +30,7 @@ /** * Export the game to a mod pack file. */ -public class HMCLModpackExportTask extends Task { +public class HMCLModpackExportTask extends Task { private final DefaultGameRepository repository; private final String version; private final List whitelist; 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 b86ceb340c..1fcc1e2f57 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -36,13 +36,13 @@ import java.util.LinkedList; import java.util.List; -public final class HMCLModpackInstallTask extends Task { +public final class HMCLModpackInstallTask extends Task { private final File zipFile; private final String name; private final HMCLGameRepository repository; private final Modpack modpack; - private final List dependencies = new LinkedList<>(); - private final List dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, String name) { DependencyManager dependency = profile.getDependency(); @@ -77,12 +77,12 @@ public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, St } @Override - public List getDependencies() { + public List> getDependencies() { return dependencies; } @Override - public List getDependents() { + public List> getDependents() { return dependents; } 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 93e5b34e4b..4094deb795 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -121,15 +121,15 @@ private void launch0() { Version version = MaintainTask.maintain(repository.getResolvedVersion(selectedVersion)); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); - TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) - .then(() -> { + TaskExecutor executor = Task.runAsync(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) + .thenCompose(() -> { if (setting.isNotCheckGame()) return null; else return dependencyManager.checkGameCompletionAsync(version); }) - .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS))) - .then(() -> { + .thenRun(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS)) + .thenCompose(() -> { try { ModpackConfiguration configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion)); if ("Curse".equals(configuration.getType())) @@ -140,8 +140,8 @@ private void launch0() { return null; } }) - .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) - .thenCompose(() -> Task.ofResult(i18n("account.methods"), () -> { + .thenRun(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN)) + .thenSupply(i18n("account.methods"), () -> { try { return account.logIn(); } catch (CredentialExpiredException e) { @@ -151,7 +151,7 @@ private void launch0() { LOG.warning("Authentication failed, try playing offline: " + e); return account.playOffline().orElseThrow(() -> e); } - })) + }) .thenApply(Schedulers.javafx(), authInfo -> { emitStatus(LoadingState.LAUNCHING); return authInfo; @@ -199,7 +199,7 @@ private void launch0() { final AtomicInteger finished = new AtomicInteger(0); @Override - public void onFinished(Task task) { + public void onFinished(Task task) { finished.incrementAndGet(); int runningTasks = executor.getRunningTasks(); Platform.runLater(() -> launchingStepsPane.setProgress(1.0 * finished.get() / runningTasks)); @@ -416,7 +416,7 @@ private void checkExit() { } } - private static class LaunchTask extends TaskResult { + private static class LaunchTask extends Task { private final ExceptionalSupplier supplier; public LaunchTask(ExceptionalSupplier supplier) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index 3b256d0442..33e5bc3f18 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -86,7 +86,7 @@ else if (manifest instanceof CurseManifest) throw new UnsupportedModpackException(); } - public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) { + public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) { profile.getRepository().markVersionAsModpack(name); ExceptionalRunnable success = () -> { @@ -117,11 +117,11 @@ else if (modpack.getManifest() instanceof HMCLModpackManifest) else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) .whenComplete(Schedulers.defaultScheduler(), success, failure) - .then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); + .thenCompose(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); else throw new IllegalStateException("Unrecognized modpack: " + modpack); } - public static Task getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException { + public static Task getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException { Modpack modpack = ModpackHelper.readModpackManifest(zipFile.toPath(), charset); switch (configuration.getType()) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java index e4d6bd6fb7..31a3bece93 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java @@ -26,7 +26,7 @@ import java.util.Objects; -public final class MultiMCInstallVersionSettingTask extends Task { +public final class MultiMCInstallVersionSettingTask extends Task { private final Profile profile; private final MultiMCInstanceConfiguration manifest; private final String version; 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 66e462d51f..572cc110e7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -205,7 +205,7 @@ public static void initialize(Stage stage) { dialog(i18n("launcher.cache_directory.invalid")); } - Task.of(JavaVersion::initialize).start(); + Task.runAsync(JavaVersion::initialize).start(); scene = new Scene(decorator.getDecorator(), 800, 519); scene.getStylesheets().setAll(config().getTheme().getStylesheets()); 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 f555d7f836..7cb490cd49 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -373,7 +373,7 @@ public static void unbindBoolean(JFXCheckBox checkBox, Property propert */ @SuppressWarnings("unchecked") @Deprecated - public static void bindEnum(JFXComboBox comboBox, Property property) { + public static void bindEnum(JFXComboBox comboBox, Property> property) { unbindEnum(comboBox); ChangeListener listener = (a, b, newValue) -> ((Property) property).setValue(property.getValue().getClass().getEnumConstants()[newValue.intValue()]); 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 ad0160dee6..790c655499 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -118,12 +118,12 @@ private void onRefreshedVersions(HMCLGameRepository repository) { if (repository.getVersionCount() == 0) { File modpackFile = new File("modpack.zip").getAbsoluteFile(); if (modpackFile.exists()) { - Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) + Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) .thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) .thenAccept(modpack -> { AtomicReference region = new AtomicReference<>(); TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) - .with(Task.of(Schedulers.javafx(), this::checkAccount)).executor(); + .withRun(Schedulers.javafx(), this::checkAccount).executor(); region.set(Controllers.taskDialog(executor, i18n("modpack.installing"))); executor.start(); }).start(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java index 00646b113f..ad955fa713 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java @@ -61,7 +61,7 @@ private void onAccept() { String password = txtPassword.getText(); progressBar.setVisible(true); lblCreationWarning.setText(""); - Task.ofResult(() -> oldAccount.logInWithPassword(password)) + Task.supplyAsync(() -> oldAccount.logInWithPassword(password)) .whenComplete(Schedulers.javafx(), authInfo -> { success.accept(authInfo); fireEvent(new DialogCloseEvent()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 579548f804..9a26ad7b51 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -195,7 +195,7 @@ private void onCreationAccept() { AccountFactory factory = cboType.getSelectionModel().getSelectedItem(); Object additionalData = getAuthAdditionalData(); - Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData)) + Task.supplyAsync(() -> factory.create(new Selector(), username, password, additionalData)) .whenComplete(Schedulers.javafx(), account -> { int oldIndex = Accounts.getAccounts().indexOf(account); if (oldIndex == -1) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index dcb2214c5f..b37dbd39c5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -104,7 +104,7 @@ private void onAddNext() { nextPane.showSpinner(); addServerPane.setDisable(true); - Task.of(() -> { + Task.runAsync(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); }).whenComplete(Schedulers.javafx(), (isDependentSucceeded, exception) -> { addServerPane.setDisable(false); 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 9db91119f5..9c79962509 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 @@ -42,7 +42,7 @@ public final class TaskListPane extends StackPane { private final AdvancedListBox listBox = new AdvancedListBox(); - private final Map nodes = new HashMap<>(); + private final Map, ProgressListNode> nodes = new HashMap<>(); private final ReadOnlyIntegerWrapper finishedTasks = new ReadOnlyIntegerWrapper(); private final ReadOnlyIntegerWrapper totTasks = new ReadOnlyIntegerWrapper(); @@ -72,12 +72,12 @@ public void onStart() { } @Override - public void onReady(Task task) { + public void onReady(Task task) { Platform.runLater(() -> totTasks.set(totTasks.getValue() + 1)); } @Override - public void onRunning(Task task) { + public void onRunning(Task task) { if (!task.getSignificance().shouldShow()) return; @@ -113,7 +113,7 @@ public void onRunning(Task task) { } @Override - public void onFinished(Task task) { + public void onFinished(Task task) { ProgressListNode node = nodes.remove(task); if (node == null) return; @@ -125,7 +125,7 @@ public void onFinished(Task task) { } @Override - public void onFailed(Task task, Throwable throwable) { + public void onFailed(Task task, Throwable throwable) { ProgressListNode node = nodes.remove(task); if (node == null) return; @@ -142,7 +142,7 @@ private static class ProgressListNode extends BorderPane { private final Label title = new Label(); private final Label state = new Label(); - public ProgressListNode(Task task) { + public ProgressListNode(Task task) { bar.progressProperty().bind(task.progressProperty()); title.setText(task.getName()); state.textProperty().bind(task.messageProperty()); 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 6f826a1a95..a00ec76a6c 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 @@ -27,7 +27,6 @@ import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.task.DownloadException; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.ui.wizard.WizardController; @@ -90,7 +89,7 @@ public Object finish(Map settings) { settings.put("success_message", i18n("install.success")); settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next)); - TaskResult ret = Task.ofResult(() -> version); + Task ret = Task.supplyAsync(() -> version); if (settings.containsKey("forge")) ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); @@ -101,7 +100,7 @@ public Object finish(Map settings) { if (settings.containsKey("optifine")) ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); - return ret.then(profile.getRepository().refreshVersionsAsync()); + return ret.thenCompose(profile.getRepository().refreshVersionsAsync()); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index 614055ae72..959b807e94 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -71,7 +71,7 @@ public void start(Map settings) { settings.put(PROFILE, profile); } - private Task finishModpackInstallingAsync(Map settings) { + private Task finishModpackInstallingAsync(Map settings) { if (!settings.containsKey(ModpackPage.MODPACK_FILE)) return null; @@ -93,7 +93,7 @@ private Task finishModpackInstallingAsync(Map settings) { return null; } else { return ModpackHelper.getInstallTask(profile, selected, name, modpack) - .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); + .thenRun(Schedulers.javafx(), () -> profile.setSelectedVersion(name)); } } 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 7a762498b8..ced4dce600 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 @@ -109,7 +109,7 @@ public ModpackPage(WizardController controller) { } spinnerPane.showSpinner(); - Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath())) + Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath())) .thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) .whenComplete(Schedulers.javafx(), manifest -> { spinnerPane.hideSpinner(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index e64696b2c4..4deceef5b4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -43,7 +43,7 @@ public void start(Map settings) { settings.put(PROFILE, profile); } - private Task finishVersionDownloadingAsync(Map settings) { + private Task finishVersionDownloadingAsync(Map settings) { GameBuilder builder = profile.getDependency().gameBuilder(); String name = (String) settings.get("name"); @@ -60,7 +60,7 @@ private Task finishVersionDownloadingAsync(Map settings) { builder.version((RemoteVersion) settings.get("optifine")); return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions()) - .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); + .thenRun(Schedulers.javafx(), () -> profile.setSelectedVersion(name)); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index f3fef3b8bd..f274d97455 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -60,8 +60,8 @@ public Object finish(Map settings) { List launcherJar = Launcher.getCurrentJarFiles(); boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null; - return new Task() { - Task dependency = null; + return new Task() { + Task dependency = null; @Override public void execute() throws Exception { @@ -80,7 +80,7 @@ public void execute() throws Exception { ), tempModpack); if (includeLauncher) { - dependency = dependency.then(Task.of(() -> { + dependency = dependency.thenRun(() -> { try (Zipper zip = new Zipper(modpackFile.toPath())) { Config exported = new Config(); @@ -109,12 +109,12 @@ public void execute() throws Exception { for (File jar : launcherJar) zip.putFile(jar, jar.getName()); } - })); + }); } } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return Collections.singleton(dependency); } }; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index 020ff62de0..b7db33443a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -54,9 +54,9 @@ public void loadVersion(Profile profile, String versionId) { LinkedList newList = new LinkedList<>(version.getLibraries()); newList.remove(library); new MaintainTask(version.setLibraries(newList)) - .then(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion)) - .with(profile.getRepository().refreshVersionsAsync()) - .with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))) + .thenCompose(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion)) + .withCompose(profile.getRepository().refreshVersionsAsync()) + .withRun(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId)) .start(); }; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 62a4da7211..1b9050e0b9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -85,7 +85,7 @@ public void loadVersion(Profile profile, String id) { public void loadMods(ModManager modManager) { this.modManager = modManager; - Task.ofResult(() -> { + Task.supplyAsync(() -> { synchronized (ModListPage.this) { JFXUtilities.runInFX(() -> loadingProperty().set(true)); modManager.refreshMods(); @@ -111,7 +111,7 @@ public void add() { List succeeded = new LinkedList<>(); List failed = new LinkedList<>(); if (res == null) return; - Task.of(() -> { + Task.runAsync(() -> { for (File file : res) { try { modManager.addMod(file); @@ -123,7 +123,7 @@ public void add() { // Actually addMod will not throw exceptions because FileChooser has already filtered files. } } - }).with(Task.of(Schedulers.javafx(), () -> { + }).withRun(Schedulers.javafx(), () -> { List prompt = new LinkedList<>(); if (!succeeded.isEmpty()) prompt.add(i18n("mods.add.success", String.join(", ", succeeded))); @@ -131,7 +131,7 @@ public void add() { prompt.add(i18n("mods.add.failed", String.join(", ", failed))); Controllers.dialog(String.join("\n", prompt), i18n("mods.add")); loadMods(modManager); - })).start(); + }).start(); } public void setParentTab(JFXTabPane parentTab) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index 17619e040d..772579c396 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -118,7 +118,7 @@ private void initialize() { FXUtils.smoothScrolling(scroll); - Task.ofResult(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> { + Task.supplyAsync(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> { javaItem.loadChildren(list.stream() .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) @@ -273,7 +273,7 @@ private void initJavaSubtitle() { VersionSetting versionSetting = lastVersionSetting; if (versionSetting == null) return; - Task.ofResult(versionSetting::getJavaVersion) + Task.supplyAsync(versionSetting::getJavaVersion) .thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path"))) .start(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPage.java index 480f49e01f..70ebd9c44c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPage.java @@ -74,6 +74,6 @@ public String getTitle() { @Override protected Object finish() { - return Task.of(i18n("world.export.wizard", worldName.get()), () -> world.export(Paths.get(path.get()), worldName.get())); + return Task.runAsync(i18n("world.export.wizard", worldName.get()), () -> world.export(Paths.get(path.get()), worldName.get())); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 53095e6d07..4cbc160aec 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -50,7 +50,7 @@ public void loadVersion(Profile profile, String id) { this.savesDir = profile.getRepository().getRunDirectory(id).toPath().resolve("saves"); setLoading(true); - Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) + Task.supplyAsync(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) .whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> { setLoading(false); if (isDependentSucceeded) @@ -72,10 +72,10 @@ public void add() { private void installWorld(File zipFile) { // Only accept one world file because user is required to confirm the new world name // Or too many input dialogs are popped. - Task.ofResult(() -> new World(zipFile.toPath())) + Task.supplyAsync(() -> new World(zipFile.toPath())) .whenComplete(Schedulers.javafx(), world -> { Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { - Task.of(() -> world.install(savesDir, name)) + Task.runAsync(() -> world.install(savesDir, name)) .whenComplete(Schedulers.javafx(), () -> { itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); resolve.run(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java index badfd68b11..999f9aa6fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java @@ -32,8 +32,8 @@ public interface AbstractWizardDisplayer extends WizardDisplayer { Queue getCancelQueue(); @Override - default void handleTask(Map settings, Task task) { - TaskExecutor executor = task.with(Task.of(Schedulers.javafx(), this::navigateToSuccess)).executor(); + default void handleTask(Map settings, Task task) { + TaskExecutor executor = task.withRun(Schedulers.javafx(), this::navigateToSuccess).executor(); TaskListPane pane = new TaskListPane(); pane.setExecutor(executor); navigateTo(pane, Navigation.NavigationDirection.FINISH); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 48fb46f0a4..41119e2e82 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -35,7 +35,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer { @Override - default void handleTask(Map settings, Task task) { + default void handleTask(Map settings, Task task) { TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> { it.fireEvent(new DialogCloseEvent()); onEnd(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java index b3bb62ed62..16caab6c97 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java @@ -106,7 +106,7 @@ public boolean canPrev() { public void onFinish() { Object result = provider.finish(settings); if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT); - else if (result instanceof Task) displayer.handleTask(settings, ((Task) result)); + else if (result instanceof Task) displayer.handleTask(settings, ((Task) result)); else if (result != null) throw new IllegalStateException("Unrecognized wizard result: " + result); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java index 43e9397ca7..23731ebe89 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java @@ -27,5 +27,5 @@ public interface WizardDisplayer { void onEnd(); void onCancel(); void navigateTo(Node page, Navigation.NavigationDirection nav); - void handleTask(Map settings, Task task); + void handleTask(Map settings, Task task); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index d2cacc977b..1be18e5522 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -99,7 +99,7 @@ public static void updateFrom(RemoteVersion version) { return; } - Task task = new HMCLDownloadTask(version, downloaded); + Task task = new HMCLDownloadTask(version, downloaded); TaskExecutor executor = task.executor(); Controllers.taskDialog(executor, i18n("message.downloading")); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index ac656d9fc2..6e5536f56e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -26,9 +26,7 @@ import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.function.ExceptionalFunction; /** @@ -69,9 +67,9 @@ public GameBuilder gameBuilder() { } @Override - public Task checkGameCompletionAsync(Version version) { - return new ParallelTask( - Task.ofThen(() -> { + public Task checkGameCompletionAsync(Version version) { + return Task.allOf( + Task.composeAsync(() -> { if (!repository.getVersionJar(version).exists()) return new GameDownloadTask(this, null, version); else @@ -83,12 +81,12 @@ public Task checkGameCompletionAsync(Version version) { } @Override - public Task checkLibraryCompletionAsync(Version version) { + public Task checkLibraryCompletionAsync(Version version) { return new GameLibrariesTask(this, version); } @Override - public TaskResult installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { + public Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); return versionList.loadAsync(gameVersion, getDownloadProvider()) .thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) @@ -96,8 +94,8 @@ public TaskResult installLibraryAsync(String gameVersion, Version versi } @Override - public TaskResult installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) { - TaskResult task; + public Task installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) { + Task task; if (libraryVersion instanceof ForgeRemoteVersion) task = new ForgeInstallTask(this, oldVersion, (ForgeRemoteVersion) libraryVersion); else if (libraryVersion instanceof LiteLoaderRemoteVersion) @@ -113,7 +111,7 @@ else if (libraryVersion instanceof OptiFineRemoteVersion) } - public ExceptionalFunction, ?> installLibraryAsync(RemoteVersion libraryVersion) { + public ExceptionalFunction, ?> installLibraryAsync(RemoteVersion libraryVersion) { return version -> installLibraryAsync(version, libraryVersion); } } 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 60b8f01d6d..c3d9994a69 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -19,9 +19,7 @@ import org.jackhuang.hmcl.download.game.*; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -48,16 +46,16 @@ public DownloadProvider getDownloadProvider() { } @Override - public Task buildAsync() { + public Task buildAsync() { return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> { Version original = JsonUtils.GSON.fromJson(rawJson, Version.class); Version version = original.setId(name).setJar(null); - Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask( + Task vanillaTask = downloadGameAsync(gameVersion, version).thenCompose(Task.allOf( new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY), new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. - ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. + ).withCompose(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. - TaskResult libraryTask = vanillaTask.thenSupply(() -> version); + Task libraryTask = vanillaTask.thenSupply(() -> version); if (toolVersions.containsKey("forge")) libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge")); @@ -76,11 +74,11 @@ public Task buildAsync() { }); } - private ExceptionalFunction, ?> libraryTaskHelper(String gameVersion, String libraryId) { + private ExceptionalFunction, ?> libraryTaskHelper(String gameVersion, String libraryId) { return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, toolVersions.get(libraryId)); } - protected Task downloadGameAsync(String gameVersion, Version version) { + protected Task downloadGameAsync(String gameVersion, Version version) { return new GameDownloadTask(dependencyManager, gameVersion, version); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java index 8dc95bc543..c627bf265f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java @@ -46,7 +46,7 @@ public interface DependencyManager { * * @return the task to check game completion. */ - Task checkGameCompletionAsync(Version version); + Task checkGameCompletionAsync(Version version); /** * Check if the game is complete. @@ -54,7 +54,7 @@ public interface DependencyManager { * * @return the task to check game completion. */ - Task checkLibraryCompletionAsync(Version version); + Task checkLibraryCompletionAsync(Version version); /** * The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine. @@ -71,7 +71,7 @@ public interface DependencyManager { * @param libraryVersion the version of being installed library. * @return the task to install the specific library. */ - Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion); + Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion); /** * Install a library to a version. @@ -81,7 +81,7 @@ public interface DependencyManager { * @param libraryVersion the remote version of being installed library. * @return the task to install the specific library. */ - Task installLibraryAsync(Version version, RemoteVersion libraryVersion); + Task installLibraryAsync(Version version, RemoteVersion libraryVersion); /** * Get registered version list. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java index 040af618f6..e25aaaef39 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java @@ -72,5 +72,5 @@ public GameBuilder version(RemoteVersion remoteVersion) { /** * @return the task that can build thw whole Minecraft environment */ - public abstract Task buildAsync(); + public abstract Task buildAsync(); } 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 c0a58dcbce..fc0e818a69 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -18,9 +18,9 @@ package org.jackhuang.hmcl.download; import org.jackhuang.hmcl.game.*; -import org.jackhuang.hmcl.task.TaskResult; +import org.jackhuang.hmcl.task.Task; -public class MaintainTask extends TaskResult { +public class MaintainTask extends Task { private final Version version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index da4cc87809..15703b3706 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -62,19 +62,19 @@ public boolean isLoaded(String gameVersion) { * @param downloadProvider DownloadProvider * @return the task to reload the remote version list. */ - public abstract Task refreshAsync(DownloadProvider downloadProvider); + public abstract Task refreshAsync(DownloadProvider downloadProvider); /** * @param gameVersion the remote version depends on * @param downloadProvider DownloadProvider * @return the task to reload the remote version list. */ - public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { + public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { return refreshAsync(downloadProvider); } - public Task loadAsync(DownloadProvider downloadProvider) { - return Task.ofThen(() -> { + public Task loadAsync(DownloadProvider downloadProvider) { + return Task.composeAsync(() -> { lock.readLock().lock(); boolean loaded; @@ -87,8 +87,8 @@ public Task loadAsync(DownloadProvider downloadProvider) { }); } - public Task loadAsync(String gameVersion, DownloadProvider downloadProvider) { - return Task.ofThen(() -> { + public Task loadAsync(String gameVersion, DownloadProvider downloadProvider) { + return Task.composeAsync(() -> { lock.readLock().lock(); boolean loaded; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index b412c09ff6..fcb999d3f6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -46,21 +46,21 @@ public boolean hasType() { } @Override - public Task loadAsync(DownloadProvider downloadProvider) { + public Task loadAsync(DownloadProvider downloadProvider) { throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); } @Override - public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { + public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) { final GetTask task = new GetTask(NetworkUtils.toURL("https://bmclapi2.bangbang93.com/forge/minecraft/" + gameVersion)); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(task); } 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 c29de94a50..222b207ce7 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 @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.versioning.VersionNumber; @@ -34,14 +33,14 @@ * * @author huangyuhui */ -public final class ForgeInstallTask extends TaskResult { +public final class ForgeInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final Version version; private Path installer; private final ForgeRemoteVersion remote; - private Task dependent; - private TaskResult dependency; + private Task dependent; + private Task dependency; public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; @@ -73,20 +72,15 @@ public void postExecute() throws Exception { } @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(dependent); } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return Collections.singleton(dependency); } - @Override - public boolean isRelyingOnDependencies() { - return false; - } - @Override public void execute() { if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index fe1250485a..bdb0d0f8a4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -49,19 +48,19 @@ import static org.jackhuang.hmcl.util.Hex.encodeHex; import static org.jackhuang.hmcl.util.Logging.LOG; -public class ForgeNewInstallTask extends TaskResult { +public class ForgeNewInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final DefaultGameRepository gameRepository; private final Version version; private final Path installer; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); private ForgeNewInstallProfile profile; private Version forgeVersion; - public ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { + ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { this.dependencyManager = dependencyManager; this.gameRepository = dependencyManager.getGameRepository(); this.version = version; @@ -80,12 +79,12 @@ else if (StringUtils.isSurrounded(literal, "[", "]")) } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @Override - public List getDependencies() { + public Collection> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java index 1c961c91d4..3736eadd1a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeOldInstallTask.java @@ -20,7 +20,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; @@ -31,21 +30,21 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -public class ForgeOldInstallTask extends TaskResult { +public class ForgeOldInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final Version version; private final Path installer; - private final List dependencies = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); - public ForgeOldInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { + ForgeOldInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) { this.dependencyManager = dependencyManager; this.version = version; this.installer = installer; } @Override - public List getDependencies() { + public List> getDependencies() { return dependencies; } 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 3f9070d08e..fb4c5ae196 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 @@ -45,12 +45,12 @@ public boolean hasType() { } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { final GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(FORGE_LIST))); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(task); } 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 9c435ce41e..378141f0bc 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 @@ -38,14 +38,14 @@ * * @author huangyuhui */ -public final class GameAssetDownloadTask extends Task { +public final class GameAssetDownloadTask extends Task { private final AbstractDependencyManager dependencyManager; private final Version version; private final AssetIndexInfo assetIndexInfo; private final File assetIndexFile; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); /** * Constructor. @@ -64,12 +64,12 @@ public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Versio } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index c13ef118c4..39d166ead4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.CacheRepository; import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.File; @@ -34,11 +33,11 @@ * * @author huangyuhui */ -public final class GameAssetIndexDownloadTask extends Task { +public final class GameAssetIndexDownloadTask extends Task { private final AbstractDependencyManager dependencyManager; private final Version version; - private final List dependencies = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); /** * Constructor. @@ -53,7 +52,7 @@ public GameAssetIndexDownloadTask(AbstractDependencyManager dependencyManager, V } @Override - public List getDependencies() { + public List> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index f0d4288f1f..47d77fe446 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -26,6 +26,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.File; +import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -33,11 +34,11 @@ * * @author huangyuhui */ -public final class GameDownloadTask extends Task { +public final class GameDownloadTask extends Task { private final DefaultDependencyManager dependencyManager; private final String gameVersion; private final Version version; - private final List dependencies = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); public GameDownloadTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version) { this.dependencyManager = dependencyManager; @@ -48,7 +49,7 @@ public GameDownloadTask(DefaultDependencyManager dependencyManager, String gameV } @Override - public List getDependencies() { + public Collection> getDependencies() { return dependencies; } 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 35519cec7b..49ca6e09f6 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 @@ -32,12 +32,12 @@ * * @author huangyuhui */ -public final class GameLibrariesTask extends Task { +public final class GameLibrariesTask extends Task { private final AbstractDependencyManager dependencyManager; private final Version version; private final List libraries; - private final List dependencies = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); /** * Constructor. @@ -64,7 +64,7 @@ public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version ve } @Override - public List getDependencies() { + public List> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java index 855e65c5c9..d246baa62e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java @@ -55,11 +55,11 @@ protected Collection getVersionsImpl(String gameVersion) { } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.getVersionListURL())); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(task); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java index 23d586c1e0..0ecece4c0b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibrariesUniqueTask.java @@ -20,7 +20,7 @@ import org.jackhuang.hmcl.game.CompatibilityRule; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.TaskResult; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.SimpleMultimap; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.versioning.VersionNumber; @@ -31,7 +31,7 @@ import java.util.List; import java.util.stream.Collectors; -public class LibrariesUniqueTask extends TaskResult { +public class LibrariesUniqueTask extends Task { private final Version version; public LibrariesUniqueTask(Version version) { 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 311ffaa1a8..b9d5e92b27 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 @@ -45,7 +45,7 @@ import static org.jackhuang.hmcl.util.DigestUtils.digest; import static org.jackhuang.hmcl.util.Hex.encodeHex; -public class LibraryDownloadTask extends Task { +public class LibraryDownloadTask extends Task { private FileDownloadTask task; protected final File jar; protected final DefaultCacheRepository cacheRepository; @@ -74,7 +74,7 @@ public LibraryDownloadTask(AbstractDependencyManager dependencyManager, File fil } @Override - public Collection getDependents() { + public Collection> getDependents() { if (cached) return Collections.emptyList(); else return Collections.singleton(task); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index d24bc5a6a3..30024cd984 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.io.NetworkUtils; import java.util.Collection; @@ -33,11 +32,11 @@ * * @author huangyuhui */ -public final class VersionJsonDownloadTask extends TaskResult { +public final class VersionJsonDownloadTask extends Task { private final String gameVersion; private final DefaultDependencyManager dependencyManager; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); private final VersionList gameVersionList; public VersionJsonDownloadTask(String gameVersion, DefaultDependencyManager dependencyManager) { @@ -52,12 +51,12 @@ public VersionJsonDownloadTask(String gameVersion, DefaultDependencyManager depe } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java index 9c3793fc41..2a14c2f79c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java @@ -19,7 +19,7 @@ import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.task.TaskResult; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -30,7 +30,7 @@ * * @author huangyuhui */ -public final class VersionJsonSaveTask extends TaskResult { +public final class VersionJsonSaveTask extends Task { private final DefaultGameRepository repository; private final Version version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java index 7451bc2ea9..da6f20c919 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java @@ -33,7 +33,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.Optional; /** * @@ -52,11 +51,11 @@ public boolean hasType() { } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST))); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(task); } 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 558714f954..33cd7da2ac 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 @@ -23,7 +23,6 @@ import org.jackhuang.hmcl.game.LibraryDownloadInfo; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.Lang; import java.util.Collection; @@ -36,13 +35,13 @@ * * @author huangyuhui */ -public final class LiteLoaderInstallTask extends TaskResult { +public final class LiteLoaderInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final Version version; private final LiteLoaderRemoteVersion remote; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, Version version, LiteLoaderRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; @@ -51,12 +50,12 @@ public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, Version } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } 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 bdc720408c..f5d48441f6 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 @@ -33,7 +33,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.Optional; /** * @@ -52,11 +51,11 @@ public boolean hasType() { } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST))); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(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 56bf747ede..0ff0f38152 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 @@ -46,11 +46,11 @@ public boolean hasType() { } @Override - public Task refreshAsync(DownloadProvider downloadProvider) { + public Task refreshAsync(DownloadProvider downloadProvider) { GetTask task = new GetTask(NetworkUtils.toURL("http://bmclapi2.bangbang93.com/optifine/versionlist")); - return new Task() { + return new Task() { @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(task); } 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 716ddfad45..444430912f 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 @@ -23,7 +23,6 @@ import org.jackhuang.hmcl.game.LibraryDownloadInfo; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskResult; import org.jackhuang.hmcl.util.Lang; import java.util.Collection; @@ -35,13 +34,13 @@ * * @author huangyuhui */ -public final class OptiFineInstallTask extends TaskResult { +public final class OptiFineInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final Version version; private final OptiFineRemoteVersion remote; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; @@ -50,12 +49,12 @@ public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version v } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java index 0aff526939..04fb45664a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java @@ -77,8 +77,8 @@ default Version getResolvedVersion(String id) throws VersionNotFoundException { */ void refreshVersions(); - default Task refreshVersionsAsync() { - return Task.of(this::refreshVersions); + default Task refreshVersionsAsync() { + return Task.runAsync(this::refreshVersions); } /** diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java index 9bac795b1e..3808404efb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java @@ -43,14 +43,14 @@ * * @author huangyuhui */ -public final class CurseCompletionTask extends Task { +public final class CurseCompletionTask extends Task { private final DefaultGameRepository repository; private final ModManager modManager; private final String version; private CurseManifest manifest = null; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); /** * Constructor. @@ -86,12 +86,12 @@ public CurseCompletionTask(DefaultDependencyManager dependencyManager, String ve } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @@ -147,7 +147,7 @@ public void execute() throws Exception { // Let this task fail if the curse manifest has not been completed. // But continue other downloads. if (!flag.get() || notFound.get()) - dependencies.add(Task.of(() -> { + dependencies.add(Task.runAsync(() -> { if (notFound.get()) throw new CurseCompletionException(new FileNotFoundException()); else diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseInstallTask.java index 86fe2b7151..77449cd5e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseInstallTask.java @@ -38,7 +38,7 @@ * * @author huangyuhui */ -public final class CurseInstallTask extends Task { +public final class CurseInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final DefaultGameRepository repository; @@ -48,8 +48,8 @@ public final class CurseInstallTask extends Task { private final String name; private final File run; private final ModpackConfiguration config; - private final List dependents = new LinkedList<>(); - private final List dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); /** * Constructor. @@ -99,12 +99,12 @@ public CurseInstallTask(DefaultDependencyManager dependencyManager, File zipFile } @Override - public Collection getDependents() { + public Collection> getDependents() { return dependents; } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return dependencies; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java index 33354e6cba..f7a05b10de 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java @@ -33,7 +33,7 @@ import static org.jackhuang.hmcl.util.DigestUtils.digest; import static org.jackhuang.hmcl.util.Hex.encodeHex; -public final class MinecraftInstanceTask extends Task { +public final class MinecraftInstanceTask extends Task { private final File zipFile; private final Charset encoding; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java index 4a94732394..291909dcd0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java @@ -31,7 +31,7 @@ import static org.jackhuang.hmcl.util.DigestUtils.digest; import static org.jackhuang.hmcl.util.Hex.encodeHex; -public class ModpackInstallTask extends Task { +public class ModpackInstallTask extends Task { private final File modpackFile; private final File dest; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java index 7adc8754dd..608f816928 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackUpdateTask.java @@ -26,14 +26,14 @@ import java.util.Collection; import java.util.Collections; -public class ModpackUpdateTask extends Task { +public class ModpackUpdateTask extends Task { private final DefaultGameRepository repository; private final String id; - private final Task updateTask; + private final Task updateTask; private final Path backupFolder; - public ModpackUpdateTask(DefaultGameRepository repository, String id, Task updateTask) { + public ModpackUpdateTask(DefaultGameRepository repository, String id, Task updateTask) { this.repository = repository; this.id = id; this.updateTask = updateTask; @@ -49,7 +49,7 @@ public ModpackUpdateTask(DefaultGameRepository repository, String id, Task updat } @Override - public Collection getDependencies() { + public Collection> getDependencies() { return Collections.singleton(updateTask); } 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 6095604ecd..06d1571f60 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -46,15 +46,15 @@ * * @author huangyuhui */ -public final class MultiMCModpackInstallTask extends Task { +public final class MultiMCModpackInstallTask extends Task { private final File zipFile; private final Modpack modpack; private final MultiMCInstanceConfiguration manifest; private final String name; private final DefaultGameRepository repository; - private final List dependencies = new LinkedList<>(); - private final List dependents = new LinkedList<>(); + private final List> dependencies = new LinkedList<>(); + private final List> dependents = new LinkedList<>(); public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, MultiMCInstanceConfiguration manifest, String name) { this.zipFile = zipFile; @@ -91,7 +91,7 @@ public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, Fil } @Override - public List getDependencies() { + public List> getDependencies() { return dependencies; } @@ -126,7 +126,7 @@ else if (Files.exists(fs.getPath("/" + manifest.getName() + "/minecraft"))) } @Override - public List getDependents() { + public List> getDependents() { return dependents; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java deleted file mode 100644 index f9d87efe73..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.function.ExceptionalSupplier; - -import java.util.Collection; -import java.util.Collections; - -/** - * A task that combines two tasks and make sure [pred] runs before succ. - * - * @author huangyuhui - */ -final class CoupleTask extends Task { - - private final boolean relyingOnDependents; - private final Task pred; - private Task succ; - private final ExceptionalSupplier supplier; - - /** - * A task that combines two tasks and make sure pred runs before succ. - * - * @param pred the task that runs before supplier. - * @param supplier a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. - * @param relyingOnDependents true if this task chain will be broken when task pred fails. - */ - CoupleTask(Task pred, ExceptionalSupplier supplier, boolean relyingOnDependents) { - this.pred = pred; - this.supplier = supplier; - this.relyingOnDependents = relyingOnDependents; - - setSignificance(TaskSignificance.MODERATE); - setName(supplier.toString()); - } - - @Override - public void execute() throws Exception { - setName(supplier.toString()); - succ = supplier.get(); - } - - @Override - public Collection getDependents() { - return pred == null ? Collections.emptySet() : Collections.singleton(pred); - } - - @Override - public Collection getDependencies() { - return succ == null ? Collections.emptySet() : Collections.singleton(succ); - } - - @Override - public boolean isRelyingOnDependents() { - return relyingOnDependents; - } -} 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 7829d02b05..670c4b6d5a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -47,7 +47,7 @@ * * @author huangyuhui */ -public class FileDownloadTask extends Task { +public class FileDownloadTask extends Task { public static class IntegrityCheck { private String algorithm; 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 376d3914a6..24fd5738b8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -36,33 +36,27 @@ /** * - * @author huang + * @author huangyuhui */ -public final class GetTask extends TaskResult { +public final class GetTask extends Task { private final URL url; private final Charset charset; private final int retry; - private final String id; private CacheRepository repository = CacheRepository.getInstance(); public GetTask(URL url) { - this(url, ID); + this(url, UTF_8); } - public GetTask(URL url, String id) { - this(url, id, UTF_8); + public GetTask(URL url, Charset charset) { + this(url, charset, 5); } - public GetTask(URL url, String id, Charset charset) { - this(url, id, charset, 5); - } - - public GetTask(URL url, String id, Charset charset, int retry) { + public GetTask(URL url, Charset charset, int retry) { this.url = url; this.charset = charset; this.retry = retry; - this.id = id; setName(url.toString()); } @@ -138,9 +132,4 @@ public void execute() throws Exception { throw new DownloadException(url, exception); } - /** - * The default task result ID. - */ - public static final String ID = "http_get"; - } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java deleted file mode 100644 index 00844573b8..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import java.util.Arrays; -import java.util.Collection; - -/** - * The tasks that provides a way to execute tasks parallelly. - * Fails when some of {@link #tasks} failed. - * - * @author huangyuhui - */ -public final class ParallelTask extends Task { - - private final Collection tasks; - - /** - * Constructor. - * - * @param tasks the tasks that can be executed parallelly. - */ - public ParallelTask(Task... tasks) { - this.tasks = Arrays.asList(tasks); - setSignificance(TaskSignificance.MINOR); - } - - public ParallelTask(Collection tasks) { - this.tasks = tasks; - setSignificance(TaskSignificance.MINOR); - } - - @Override - public void execute() { - } - - @Override - public Collection getDependents() { - return tasks; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java deleted file mode 100644 index f8bd7f3d97..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; - -/** - * - * @author huangyuhui - */ -class SimpleTask extends Task { - - private final ExceptionalRunnable closure; - private final Scheduler scheduler; - - public SimpleTask(String name, ExceptionalRunnable closure, Scheduler scheduler) { - this.closure = closure; - this.scheduler = scheduler; - - if (name == null) { - setSignificance(TaskSignificance.MINOR); - setName(closure.toString()); - } else { - setName(name); - } - } - - @Override - public Scheduler getScheduler() { - return scheduler; - } - - @Override - public void execute() throws Exception { - closure.run(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java deleted file mode 100644 index 22111f6543..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.function.ExceptionalFunction; -import org.jackhuang.hmcl.util.function.ExceptionalSupplier; - -import java.util.concurrent.Callable; - -/** - * - * @author huangyuhui - */ -class SimpleTaskResult extends TaskResult { - - private final Callable callable; - - public SimpleTaskResult(Callable callable) { - this.callable = callable; - } - - public SimpleTaskResult(ExceptionalSupplier supplier) { - this.callable = supplier.toCallable(); - } - - @Override - public void execute() throws Exception { - setResult(callable.call()); - } -} 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 358184f8a6..292ae08f6c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -27,13 +27,16 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.ReflectionHelper; import org.jackhuang.hmcl.util.function.ExceptionalConsumer; +import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import java.util.function.Consumer; import java.util.logging.Level; /** @@ -41,15 +44,15 @@ * * @author huangyuhui */ -public abstract class Task { +public abstract class Task { private final EventManager onDone = new EventManager<>(); - private TaskSignificance significance = TaskSignificance.MAJOR; - /** * True if not logging when executing this task. */ + private TaskSignificance significance = TaskSignificance.MAJOR; + public final TaskSignificance getSignificance() { return significance; } @@ -58,6 +61,7 @@ public void setSignificance(TaskSignificance significance) { this.significance = significance; } + // state private TaskState state = TaskState.READY; public TaskState getState() { @@ -68,6 +72,7 @@ void setState(TaskState state) { this.state = state; } + // last exception private Exception lastException; public Exception getLastException() { @@ -85,6 +90,7 @@ public Scheduler getScheduler() { return Schedulers.defaultScheduler(); } + // dependents succeeded private boolean dependentsSucceeded = false; public boolean isDependentsSucceeded() { @@ -95,6 +101,7 @@ void setDependentsSucceeded() { dependentsSucceeded = true; } + // dependencies succeeded private boolean dependenciesSucceeded = false; public boolean isDependenciesSucceeded() { @@ -123,17 +130,49 @@ public boolean isRelyingOnDependencies() { return true; } + // name private String name = getClass().getName(); public String getName() { return name; } - public Task setName(String name) { + public Task setName(String name) { this.name = name; return this; } + // result + private T result; + private Consumer resultConsumer; + + /** + * Returns the result of this task. + * + * The result will be generated only if the execution is completed. + */ + public T getResult() { + return result; + } + + protected void setResult(T result) { + this.result = result; + if (resultConsumer != null) + resultConsumer.accept(result); + } + + /** + * Sync the result of this task by given action. + * + * @param action the action to perform when result of this task changed + * @return this Task + */ + public Task storeTo(Consumer action) { + this.resultConsumer = action; + return this; + } + + // execution public boolean doPreExecute() { return false; } @@ -171,7 +210,7 @@ public void postExecute() throws Exception {} /** * The collection of sub-tasks that should execute **before** this task running. */ - public Collection getDependents() { + public Collection> getDependents() { return Collections.emptySet(); } @@ -179,7 +218,7 @@ public Collection getDependents() { * The collection of sub-tasks that should execute **after** this task running. * Will not be executed if execution fails. */ - public Collection getDependencies() { + public Collection> getDependencies() { return Collections.emptySet(); } @@ -232,15 +271,15 @@ public final void run() throws Exception { if (getSignificance().shouldLog()) Logging.LOG.log(Level.FINE, "Executing task: " + getName()); - for (Task task : getDependents()) + for (Task task : getDependents()) doSubTask(task); execute(); - for (Task task : getDependencies()) + for (Task task : getDependencies()) doSubTask(task); onDone.fireEvent(new TaskEvent(this, this, false)); } - private void doSubTask(Task task) throws Exception { + private void doSubTask(Task task) throws Exception { message.bind(task.message); progress.bind(task.progress); task.run(); @@ -273,61 +312,240 @@ public final boolean test() { return executor().test(); } - public final Task then(Task b) { - return then(convert(b)); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param fn the function to use to compute the value of the returned Task + * @param the function's return type + * @return the new Task + */ + public Task thenApply(ExceptionalFunction fn) { + return thenApply(Schedulers.defaultScheduler(), fn); + } + + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned Task + * @param the function's return type + * @return the new Task + */ + public Task thenApply(Scheduler scheduler, ExceptionalFunction fn) { + return thenApply(getCaller(), scheduler, fn); + } + + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param name the name of this new Task for displaying + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned Task + * @param the function's return type + * @return the new Task + */ + public Task thenApply(String name, Scheduler scheduler, ExceptionalFunction fn) { + return new UniApply<>(name, scheduler, fn); + } + + /** + * Returns a new Task that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the + * returned Task + * @return the new Task + */ + public Task thenAccept(ExceptionalConsumer action) { + return thenAccept(Schedulers.defaultScheduler(), action); + } + + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenAccept(Scheduler scheduler, ExceptionalConsumer action) { + return thenAccept(getCaller(), scheduler, action); + } + + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param name the name of this new Task for displaying + * @param action the action to perform before completing the returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenAccept(String name, Scheduler scheduler, ExceptionalConsumer action) { + return thenApply(name, scheduler, result -> { + action.accept(result); + return null; + }); + } + + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the default Scheduler. + * + * @param action the action to perform before completing the + * returned Task + * @return the new Task + */ + public Task thenRun(ExceptionalRunnable action) { + return thenRun(Schedulers.defaultScheduler(), action); + } + + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the supplied Scheduler. + * + * @param action the action to perform before completing the + * returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenRun(Scheduler scheduler, ExceptionalRunnable action) { + return thenRun(getCaller(), scheduler, action); + } + + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the supplied Scheduler. + * + * @param name the name of this new Task for displaying + * @param action the action to perform before completing the + * returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenRun(String name, Scheduler scheduler, ExceptionalRunnable action) { + return thenApply(name, scheduler, ignore -> { + action.run(); + return null; + }); } - public final Task then(ExceptionalSupplier b) { - return new CoupleTask(this, b, true); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the default Scheduler. + * + * @param fn the function to use to compute the value of the returned Task + * @param the function's return type + * @return the new Task + */ + public final Task thenSupply(Callable fn) { + return thenCompose(() -> Task.supplyAsync(fn)); } /** - * Returns a new TaskResult that, when this task completes + * Returns a new Task that, when this task completes * normally, is executed using the default Scheduler. * - * @param fn the function to use to compute the value of the returned TaskResult + * @param name the name of this new Task for displaying + * @param fn the function to use to compute the value of the returned Task * @param the function's return type - * @return the new TaskResult + * @return the new Task */ - public final TaskResult thenSupply(Callable fn) { - return thenCompose(() -> Task.ofResult(fn)); + public final Task thenSupply(String name, Callable fn) { + return thenCompose(() -> Task.supplyAsync(name, fn)); } /** - * Returns a new TaskResult that, when this task completes + * Returns a new Task that, when this task completes + * normally, is executed. + * + * @param other the another Task + * @param the type of the returned Task's result + * @return the Task + */ + public final Task thenCompose(Task other) { + return thenCompose(() -> other); + } + + /** + * Returns a new Task that, when this task completes * normally, is executed. * - * @param fn the function returning a new TaskResult - * @param the type of the returned TaskResult's result - * @return the TaskResult + * @param fn the function returning a new Task + * @param the type of the returned Task's result + * @return the Task */ - public final TaskResult thenCompose(ExceptionalSupplier, ?> fn) { - return new TaskResult() { - TaskResult then; + public final Task thenCompose(ExceptionalSupplier, ?> fn) { + return new UniCompose<>(fn, true); + } - @Override - public Collection getDependents() { - return Collections.singleton(Task.this); - } + /** + * Returns a new Task that, when this task completes + * normally, is executed with result of this task as the argument + * to the supplied function. + * + * @param fn the function returning a new Task + * @param the type of the returned Task's result + * @return the Task + */ + public Task thenCompose(ExceptionalFunction, E> fn) { + return new UniCompose<>(fn, true); + } - @Override - public void execute() throws Exception { - then = fn.get().storeTo(this::setResult); - } + public final Task withCompose(Task other) { + return withCompose(() -> other); + } - @Override - public Collection getDependencies() { - return then == null ? Collections.emptyList() : Collections.singleton(then); - } - }; + public final Task withCompose(ExceptionalSupplier, E> fn) { + return new UniCompose<>(fn, false); } - public final Task with(Task b) { - return with(convert(b)); + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the default Scheduler. + * + * @param action the action to perform before completing the + * returned Task + * @return the new Task + */ + public Task withRun(ExceptionalRunnable action) { + return withRun(Schedulers.defaultScheduler(), action); + } + + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the supplied Scheduler. + * + * @param action the action to perform before completing the + * returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task withRun(Scheduler scheduler, ExceptionalRunnable action) { + return withRun(getCaller(), scheduler, action); } - public final Task with(ExceptionalSupplier b) { - return new CoupleTask(this, b, false); + /** + * Returns a new Task that, when this task completes + * normally, executes the given action using the supplied Scheduler. + * + * @param name the name of this new Task for displaying + * @param action the action to perform before completing the + * returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task withRun(String name, Scheduler scheduler, ExceptionalRunnable action) { + return new UniCompose<>(() -> Task.runAsync(name, scheduler, action), false); } /** @@ -344,7 +562,7 @@ public final Task with(ExceptionalSupplier b) { * @param action the action to perform * @return the new Task */ - public final Task whenComplete(FinalizedCallback action) { + public final Task whenComplete(FinalizedCallback action) { return whenComplete(Schedulers.defaultScheduler(), action); } @@ -364,8 +582,8 @@ public final Task whenComplete(FinalizedCallback action) { * @param scheduler the executor to use for asynchronous execution * @return the new Task */ - public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) { - return new Task() { + public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + return new Task() { { setSignificance(TaskSignificance.MODERATE); } @@ -389,7 +607,7 @@ public void execute() throws Exception { } @Override - public Collection getDependents() { + public Collection> getDependents() { return Collections.singleton(Task.this); } @@ -400,6 +618,25 @@ public boolean isRelyingOnDependents() { }.setName(getCaller()); } + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked with the + * result (or {@code null} if none), a boolean value represents the + * execution status of this task, and the exception (or {@code null} + * if none) of this task as arguments. The returned task is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned task exceptionally completes with this + * exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, FinalizedCallbackWithResult action) { + return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception))); + } + /** * Returns a new Task with the same exception as this task, that executes * the given actions when this task completes. @@ -415,7 +652,7 @@ public boolean isRelyingOnDependents() { * @param failure the action to perform when this task exceptionally returned * @return the new Task */ - public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { + public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { return whenComplete(scheduler, (isDependentSucceeded, exception) -> { if (isDependentSucceeded) { if (success != null) @@ -433,44 +670,114 @@ public final Task whenComplete(Sche }); } - public static Task of(ExceptionalRunnable closure) { - return of(Schedulers.defaultScheduler(), closure); + /** + * Returns a new Task with the same exception as this task, that executes + * the given actions when this task completes. + * + *

When this task is complete, the given success action is invoked with + * the result, the given failure action is invoked with the exception of + * this task. The returned task is completed when the action returns. If + * the supplied action itself encounters an exception, then the returned + * task exceptionally completes with this exception unless this task also + * completed exceptionally. + * + * @param success the action to perform when this task successfully completed + * @param failure the action to perform when this task exceptionally returned + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { + return whenComplete(scheduler, () -> success.accept(getResult()), failure); + } + + public static Task runAsync(ExceptionalRunnable closure) { + return runAsync(Schedulers.defaultScheduler(), closure); } - public static Task of(String name, ExceptionalRunnable closure) { - return of(name, Schedulers.defaultScheduler(), closure); + public static Task runAsync(String name, ExceptionalRunnable closure) { + return runAsync(name, Schedulers.defaultScheduler(), closure); } - public static Task of(Scheduler scheduler, ExceptionalRunnable closure) { - return of(getCaller(), scheduler, closure); + public static Task runAsync(Scheduler scheduler, ExceptionalRunnable closure) { + return runAsync(getCaller(), scheduler, closure); } - public static Task of(String name, Scheduler scheduler, ExceptionalRunnable closure) { - return new SimpleTask(name, closure, scheduler); + public static Task runAsync(String name, Scheduler scheduler, ExceptionalRunnable closure) { + return new SimpleTask<>(closure.toCallable(), scheduler).setName(name); + } + + public static Task composeAsync(ExceptionalSupplier, ?> fn) { + return new Task() { + Task then; + + @Override + public void execute() throws Exception { + then = fn.get(); + if (then != null) + then.storeTo(this::setResult); + } + + @Override + public Collection> getDependencies() { + return then == null ? Collections.emptySet() : Collections.singleton(then); + } + }; } - public static Task ofThen(ExceptionalSupplier b) { - return new CoupleTask(null, b, true); + public static Task supplyAsync(Callable callable) { + return supplyAsync(getCaller(), callable); } - public static TaskResult ofResult(Callable callable) { - return ofResult(getCaller(), callable); + public static Task supplyAsync(Scheduler scheduler, Callable callable) { + return supplyAsync(getCaller(), scheduler, callable); } - public static TaskResult ofResult(String name, Callable callable) { - return new SimpleTaskResult<>(callable).setName(name); + public static Task supplyAsync(String name, Callable callable) { + return supplyAsync(name, Schedulers.defaultScheduler(), callable); } - private static ExceptionalSupplier convert(Task t) { - return new ExceptionalSupplier() { + public static Task supplyAsync(String name, Scheduler scheduler, Callable callable) { + return new SimpleTask<>(callable, scheduler).setName(name); + } + + /** + * Returns a new Task that is completed when all of the given Tasks + * complete. If any of the given Tasks complete exceptionally, + * then the returned Task also does so. Otherwise, the results, if + * any, of the given Tasks are not reflected in the returned Task, + * but may be obtained by inspecting them individually. If no Tasks + * are provided, returns a Task completed with the value {@code null}. + * + * @param tasks the Tasks + * @return a new Task that is completed when all of the given Tasks complete + */ + public static Task allOf(Task... tasks) { + return allOf(Arrays.asList(tasks)); + } + + /** + * Returns a new Task that is completed when all of the given Tasks + * complete. If any of the given Tasks complete exceptionally, + * then the returned Task also does so. Otherwise, the results, if + * any, of the given Tasks are not reflected in the returned Task, + * but may be obtained by inspecting them individually. If no Tasks + * are provided, returns a Task completed with the value {@code null}. + * + * @param tasks the Tasks + * @return a new Task that is completed when all of the given Tasks complete + */ + public static Task allOf(Collection> tasks) { + return new Task() { + { + setSignificance(TaskSignificance.MINOR); + } + @Override - public Task get() { - return t; + public void execute() { } @Override - public String toString() { - return t.getName(); + public Collection> getDependents() { + return tasks; } }; } @@ -501,7 +808,118 @@ public interface FinalizedCallback { void execute(boolean isDependentSucceeded, Exception exception) throws Exception; } - static String getCaller() { + public interface FinalizedCallbackWithResult { + void execute(T result, boolean isDependentSucceeded, Exception exception) throws Exception; + } + + private static String getCaller() { return ReflectionHelper.getCaller(packageName -> !"org.jackhuang.hmcl.task".equals(packageName)).toString(); } + + private static final class SimpleTask extends Task { + + private final Callable callable; + private final Scheduler scheduler; + + SimpleTask(Callable callable, Scheduler scheduler) { + this.callable = callable; + this.scheduler = scheduler; + } + + @Override + public Scheduler getScheduler() { + return scheduler; + } + + @Override + public void execute() throws Exception { + setResult(callable.call()); + } + } + + private class UniApply extends Task { + private final Scheduler scheduler; + private final ExceptionalFunction callable; + + UniApply(String name, Scheduler scheduler, ExceptionalFunction callable) { + this.scheduler = scheduler; + this.callable = callable; + + setName(name); + } + + @Override + public Collection> getDependents() { + return Collections.singleton(Task.this); + } + + @Override + public Scheduler getScheduler() { + return scheduler; + } + + @Override + public void execute() throws Exception { + setResult(callable.apply(Task.this.getResult())); + } + } + + /** + * A task that combines two tasks and make sure [pred] runs before succ. + * + * @author huangyuhui + */ + private final class UniCompose extends Task { + + private final boolean relyingOnDependents; + private Task succ; + private final ExceptionalFunction, ?> fn; + + /** + * A task that combines two tasks and make sure pred runs before succ. + * + * @param fn a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. + * @param relyingOnDependents true if this task chain will be broken when task pred fails. + */ + UniCompose(ExceptionalSupplier, ?> fn, boolean relyingOnDependents) { + this(result -> fn.get(), relyingOnDependents); + } + + /** + * A task that combines two tasks and make sure pred runs before succ. + * + * @param fn a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. + * @param relyingOnDependents true if this task chain will be broken when task pred fails. + */ + UniCompose(ExceptionalFunction, ?> fn, boolean relyingOnDependents) { + this.fn = fn; + this.relyingOnDependents = relyingOnDependents; + + setSignificance(TaskSignificance.MODERATE); + setName(fn.toString()); + } + + @Override + public void execute() throws Exception { + setName(fn.toString()); + succ = fn.apply(Task.this.getResult()); + if (succ != null) + succ.storeTo(this::setResult); + } + + @Override + public Collection> getDependents() { + return Collections.singleton(Task.this); + } + + @Override + public Collection> getDependencies() { + return succ == null ? Collections.emptySet() : Collections.singleton(succ); + } + + @Override + public boolean isRelyingOnDependents() { + return relyingOnDependents; + } + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskEvent.java index 7478799125..94edbede06 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskEvent.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskEvent.java @@ -25,16 +25,16 @@ */ public class TaskEvent extends Event { - private final Task task; + private final Task task; private final boolean failed; - public TaskEvent(Object source, Task task, boolean failed) { + public TaskEvent(Object source, Task task, boolean failed) { super(source); this.task = task; this.failed = failed; } - public Task getTask() { + public Task getTask() { return task; } 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 3cbf487af6..b7b5be421e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -22,7 +22,6 @@ import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -32,15 +31,13 @@ */ public final class TaskExecutor { - private final Task firstTask; + private final Task firstTask; private final List taskListeners = new LinkedList<>(); - private boolean canceled = false; private Exception lastException; private final AtomicInteger totTask = new AtomicInteger(0); - private final ConcurrentLinkedQueue> workerQueue = new ConcurrentLinkedQueue<>(); - private Scheduler scheduler = Schedulers.newThread(); + private CompletableFuture future; - public TaskExecutor(Task task) { + public TaskExecutor(Task task) { this.firstTask = task; } @@ -48,222 +45,204 @@ public void addTaskListener(TaskListener taskListener) { taskListeners.add(taskListener); } - public boolean isCanceled() { - return canceled; - } - public Exception getLastException() { return lastException; } - public void setScheduler(Scheduler scheduler) { - this.scheduler = Objects.requireNonNull(scheduler); - } - public TaskExecutor start() { taskListeners.forEach(TaskListener::onStart); - workerQueue.add(scheduler.schedule(() -> { - boolean flag = executeTasks(Collections.singleton(firstTask)); - taskListeners.forEach(it -> it.onStop(flag, this)); - })); + future = executeTasks(Collections.singleton(firstTask)) + .thenApplyAsync(exception -> { + boolean success = exception == null; + taskListeners.forEach(it -> it.onStop(success, this)); + return success; + }) + .exceptionally(e -> { + Lang.handleUncaughtException(e instanceof UncheckedThrowable ? e.getCause() : e); + return false; + }); return this; } public boolean test() { - taskListeners.forEach(TaskListener::onStart); - AtomicBoolean flag = new AtomicBoolean(true); - Future future = scheduler.schedule(() -> { - flag.set(executeTasks(Collections.singleton(firstTask))); - taskListeners.forEach(it -> it.onStop(flag.get(), this)); - }); - workerQueue.add(future); + start(); try { - future.get(); + return future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException | CancellationException e) { } - return flag.get(); + return false; } /** * Cancel the subscription ant interrupt all tasks. */ public synchronized void cancel() { - canceled = true; - - while (!workerQueue.isEmpty()) { - Future future = workerQueue.poll(); - if (future != null) - future.cancel(true); + if (future == null) { + throw new IllegalStateException("Cannot cancel a not started TaskExecutor"); } + + future.cancel(true); } - private boolean executeTasks(Collection tasks) throws InterruptedException { - if (tasks.isEmpty()) - return true; - - totTask.addAndGet(tasks.size()); - AtomicBoolean success = new AtomicBoolean(true); - CountDownLatch latch = new CountDownLatch(tasks.size()); - for (Task task : tasks) { - if (canceled) - return false; - Invoker invoker = new Invoker(task, latch, success); - try { - Future future = scheduler.schedule(invoker); - if (future != null) - workerQueue.add(future); - } catch (RejectedExecutionException e) { - throw new InterruptedException(); - } - } + private CompletableFuture executeTasks(Collection> tasks) { + if (tasks == null || tasks.isEmpty()) + return CompletableFuture.completedFuture(null); + + return CompletableFuture.completedFuture(null) + .thenComposeAsync(unused -> { + totTask.addAndGet(tasks.size()); + + return CompletableFuture.allOf(tasks.stream() + .map(task -> CompletableFuture.completedFuture(null) + .thenComposeAsync(unused2 -> executeTask(task)) + ).toArray(CompletableFuture[]::new)); + }) + .thenApplyAsync(unused -> (Exception) null) + .exceptionally(throwable -> { + if (throwable instanceof Exception) { + return (Exception) throwable; + } else { + // If an error occurred, we just rethrow it. + throw new UncheckedThrowable(throwable); + } + }); + } - if (canceled) - return false; + private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runnable) { + scheduleTo(scheduler, runnable, null); + } + private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runnable, Runnable finalize) { try { - latch.await(); + scheduler.schedule(runnable).get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof Exception) + rethrow(e.getCause()); + else + throw new UncheckedException(e); } catch (InterruptedException e) { - return false; + throw new UncheckedException(e); + } finally { + if (finalize != null) + finalize.run(); } - return success.get() && !canceled; } - private boolean executeTask(Task task) { - if (canceled) { - task.setState(Task.TaskState.FAILED); - task.setLastException(new CancellationException()); - return false; - } - - task.setState(Task.TaskState.READY); - - if (task.getSignificance().shouldLog()) - Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); + private CompletableFuture executeTask(Task task) { + return CompletableFuture.completedFuture(null).thenComposeAsync(unused -> { + task.setState(Task.TaskState.READY); - taskListeners.forEach(it -> it.onReady(task)); + if (task.getSignificance().shouldLog()) + Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); - boolean flag = false; + taskListeners.forEach(it -> it.onReady(task)); - try { if (task.doPreExecute()) { - try { - task.getScheduler().schedule(task::preExecute).get(); - } catch (ExecutionException e) { - if (e.getCause() instanceof Exception) - throw (Exception) e.getCause(); - else - throw e; - } + scheduleTo(task.getScheduler(), task::preExecute); } - Collection dependents = task.getDependents(); - boolean doDependentsSucceeded = executeTasks(dependents); - Exception dependentsException = dependents.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); - if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) { + return executeTasks(task.getDependents()); + }).thenComposeAsync(dependentsException -> { + boolean isDependentsSucceeded = dependentsException == null; + + if (!isDependentsSucceeded && task.isRelyingOnDependents()) { task.setLastException(dependentsException); - throw new CancellationException(); + rethrow(dependentsException); } - if (doDependentsSucceeded) + if (isDependentsSucceeded) task.setDependentsSucceeded(); - try { - task.getScheduler().schedule(() -> { - task.setState(Task.TaskState.RUNNING); - taskListeners.forEach(it -> it.onRunning(task)); - task.execute(); - }).get(); - } catch (ExecutionException e) { - if (e.getCause() instanceof Exception) - throw (Exception) e.getCause(); - else - throw e; - } finally { - task.setState(Task.TaskState.EXECUTED); - } + scheduleTo(task.getScheduler(), () -> { + task.setState(Task.TaskState.RUNNING); + taskListeners.forEach(it -> it.onRunning(task)); + task.execute(); + }, () -> task.setState(Task.TaskState.EXECUTED)); - Collection dependencies = task.getDependencies(); - boolean doDependenciesSucceeded = executeTasks(dependencies); - Exception dependenciesException = dependencies.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null); + return executeTasks(task.getDependencies()); + }).thenApplyAsync(dependenciesException -> { + boolean isDependenciesSucceeded = dependenciesException == null; - if (doDependenciesSucceeded) + if (isDependenciesSucceeded) task.setDependenciesSucceeded(); if (task.doPostExecute()) { - try { - task.getScheduler().schedule(task::postExecute).get(); - } catch (ExecutionException e) { - if (e.getCause() instanceof Exception) - throw (Exception) e.getCause(); - else - throw e; - } + scheduleTo(task.getScheduler(), task::postExecute); } - if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { + if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) { Logging.LOG.severe("Subtasks failed for " + task.getName()); task.setLastException(dependenciesException); - throw new CancellationException(); + rethrow(dependenciesException); } - flag = true; if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); } task.onDone().fireEvent(new TaskEvent(this, task, false)); taskListeners.forEach(it -> it.onFinished(task)); - } catch (InterruptedException e) { - task.setLastException(e); - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); - } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } catch (CancellationException | RejectedExecutionException e) { - if (task.getLastException() == null) + + task.setState(Task.TaskState.SUCCEEDED); + + return null; + }).exceptionally(throwable -> { + if (!(throwable instanceof Exception)) + throw new UncheckedThrowable(throwable); + Exception e = throwable instanceof UncheckedException ? (Exception) throwable.getCause() : (Exception) throwable; + if (e instanceof InterruptedException) { task.setLastException(e); - } catch (Exception e) { - task.setLastException(e); - lastException = e; - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); + } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { + if (task.getLastException() == null) + task.setLastException(e); + } else { + task.setLastException(e); + lastException = e; + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } - task.setState(flag ? Task.TaskState.SUCCEEDED : Task.TaskState.FAILED); - return flag; + + task.setState(Task.TaskState.FAILED); + + throw new UncheckedException(e); + }); } public int getRunningTasks() { return totTask.get(); } - private class Invoker implements ExceptionalRunnable { - - private final Task task; - private final CountDownLatch latch; - private final AtomicBoolean success; + private static class UncheckedException extends RuntimeException { - public Invoker(Task task, CountDownLatch latch, AtomicBoolean success) { - this.task = task; - this.latch = latch; - this.success = success; + UncheckedException(Exception exception) { + super(exception); } + } - @Override - public void run() { - try { - Thread.currentThread().setName(task.getName()); - if (!executeTask(task)) - success.set(false); - } finally { - latch.countDown(); - } + private static class UncheckedThrowable extends RuntimeException { + + UncheckedThrowable(Throwable throwable) { + super(throwable); } + } + private static void rethrow(Throwable e) { + if (e instanceof RuntimeException) { // including UncheckedException and UncheckedThrowable + throw (RuntimeException) e; + } else if (e instanceof Exception) { + throw new UncheckedException((Exception) e); + } else { + throw new UncheckedThrowable(e); + } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java index 89bb84895f..b1386aa05a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java @@ -28,16 +28,16 @@ public abstract class TaskListener implements EventListener { public void onStart() { } - public void onReady(Task task) { + public void onReady(Task task) { } - public void onRunning(Task task) { + public void onRunning(Task task) { } - public void onFinished(Task task) { + public void onFinished(Task task) { } - public void onFailed(Task task, Throwable throwable) { + public void onFailed(Task task, Throwable throwable) { onFinished(task); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java deleted file mode 100644 index cc8a3485c9..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.function.ExceptionalConsumer; -import org.jackhuang.hmcl.util.function.ExceptionalFunction; - -import java.util.Collection; -import java.util.Collections; -import java.util.function.Consumer; - -/** - * A task that has a result. - * - * @author huangyuhui - */ -public abstract class TaskResult extends Task { - - private T result; - private Consumer resultConsumer; - - @Override - public TaskResult setName(String name) { - super.setName(name); - return this; - } - - /** - * Returns the result of this task. - * - * The result will be generated only if the execution is completed. - */ - public T getResult() { - return result; - } - - protected void setResult(T result) { - this.result = result; - if (resultConsumer != null) - resultConsumer.accept(result); - } - - /** - * Sync the result of this task by given action. - * - * @param action the action to perform when result of this task changed - * @return this TaskResult - */ - public TaskResult storeTo(Consumer action) { - this.resultConsumer = action; - return this; - } - - /** - * Returns a new TaskResult that, when this task completes - * normally, is executed with result of this task as the argument - * to the supplied function. - * - * @param fn the function returning a new TaskResult - * @param the type of the returned TaskResult's result - * @return the TaskResult - */ - public TaskResult thenCompose(ExceptionalFunction, E> fn) { - return new TaskResult() { - TaskResult then; - - @Override - public Collection getDependents() { - return Collections.singleton(TaskResult.this); - } - - @Override - public void execute() throws Exception { - then = fn.apply(TaskResult.this.getResult()).storeTo(this::setResult); - } - - @Override - public Collection getDependencies() { - return then == null ? Collections.emptyList() : Collections.singleton(then); - } - }; - } - - /** - * Returns a new Task that, when this task completes - * normally, is executed with this task as the argument - * to the supplied function. - * - * @param fn the function returning a new Task - * @return the Task - */ - public Task then(ExceptionalFunction fn) { - return new CoupleTask(this, () -> fn.apply(getResult()), true); - } - - /** - * Returns a new TaskResult that, when this task completes - * normally, is executed using the default Scheduler, with this - * task's result as the argument to the supplied function. - * - * @param fn the function to use to compute the value of the returned TaskResult - * @param the function's return type - * @return the new TaskResult - */ - public TaskResult thenApply(ExceptionalFunction fn) { - return thenApply(Schedulers.defaultScheduler(), fn); - } - - /** - * Returns a new TaskResult that, when this task completes - * normally, is executed using the supplied Scheduler, with this - * task's result as the argument to the supplied function. - * - * @param scheduler the executor to use for asynchronous execution - * @param fn the function to use to compute the value of the returned TaskResult - * @param the function's return type - * @return the new TaskResult - */ - public TaskResult thenApply(Scheduler scheduler, ExceptionalFunction fn) { - return thenApply(getCaller(), scheduler, fn); - } - - /** - * Returns a new TaskResult that, when this task completes - * normally, is executed using the supplied Scheduler, with this - * task's result as the argument to the supplied function. - * - * @param name the name of this new TaskResult for displaying - * @param scheduler the executor to use for asynchronous execution - * @param fn the function to use to compute the value of the returned TaskResult - * @param the function's return type - * @return the new TaskResult - */ - public TaskResult thenApply(String name, Scheduler scheduler, ExceptionalFunction fn) { - return new Subtask<>(name, scheduler, fn); - } - - /** - * Returns a new Task that, when this task completes - * normally, is executed using the default Scheduler, with this - * task's result as the argument to the supplied action. - * - * @param action the action to perform before completing the - * returned Task - * @return the new Task - */ - public Task thenAccept(ExceptionalConsumer action) { - return thenAccept(Schedulers.defaultScheduler(), action); - } - - /** - * Returns a new Task that, when this task completes - * normally, is executed using the supplied Scheduler, with this - * task's result as the argument to the supplied action. - * - * @param action the action to perform before completing the returned Task - * @param scheduler the executor to use for asynchronous execution - * @return the new Task - */ - public Task thenAccept(Scheduler scheduler, ExceptionalConsumer action) { - return new CoupleTask(this, () -> Task.of(scheduler, () -> action.accept(getResult())), true); - } - - /** - * Returns a new Task with the same exception as this task, that executes - * the given actions when this task completes. - * - *

When this task is complete, the given success action is invoked with - * the result, the given failure action is invoked with the exception of - * this task. The returned task is completed when the action returns. If - * the supplied action itself encounters an exception, then the returned - * task exceptionally completes with this exception unless this task also - * completed exceptionally. - * - * @param success the action to perform when this task successfully completed - * @param failure the action to perform when this task exceptionally returned - * @return the new Task - */ - public Task whenComplete(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { - return whenComplete(scheduler, () -> success.accept(getResult()), failure); - } - - /** - * Returns a new Task with the same exception as this task, that executes - * the given action when this task completes. - * - *

When this task is complete, the given action is invoked with the - * result (or {@code null} if none), a boolean value represents the - * execution status of this task, and the exception (or {@code null} - * if none) of this task as arguments. The returned task is completed - * when the action returns. If the supplied action itself encounters an - * exception, then the returned task exceptionally completes with this - * exception unless this task also completed exceptionally. - * - * @param action the action to perform - * @return the new Task - */ - public Task whenComplete(Scheduler scheduler, FinalizedCallback action) { - return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception))); - } - - private class Subtask extends TaskResult { - private final Scheduler scheduler; - private final ExceptionalFunction callable; - - public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { - this.scheduler = scheduler; - this.callable = callable; - - setName(name); - } - - @Override - public Collection getDependents() { - return Collections.singleton(TaskResult.this); - } - - @Override - public Scheduler getScheduler() { - return scheduler; - } - - @Override - public void execute() throws Exception { - setResult(callable.apply(TaskResult.this.getResult())); - } - } - - public interface FinalizedCallback { - void execute(V result, boolean isDependentSucceeded, Exception exception) throws Exception; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalRunnable.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalRunnable.java index 2ba87acb30..cfee8fcea9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalRunnable.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/function/ExceptionalRunnable.java @@ -27,15 +27,11 @@ public interface ExceptionalRunnable { void run() throws E; - default Callable toCallable() { + default Callable toCallable() { return () -> { run(); return null; }; } - static ExceptionalRunnable fromRunnable(Runnable r) { - return r::run; - } - } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java new file mode 100644 index 0000000000..5520461bbc --- /dev/null +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java @@ -0,0 +1,18 @@ +package org.jackhuang.hmcl.util; + +import org.jackhuang.hmcl.task.Task; +import org.junit.Assert; +import org.junit.Test; + +public class TaskTest { + @Test + public void testWhenComplete() { + Task.composeAsync(() -> Task.allOf( + Task.allOf(Task.runAsync(() -> { + throw new Exception(); + })) + )).whenComplete(((isDependentSucceeded, exception) -> { + Assert.assertFalse(isDependentSucceeded); + })).test(); + } +} From eeef76594f08e5fc6b24592b5ad8a1ff66cde257 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 25 Feb 2019 22:17:30 +0800 Subject: [PATCH 0053/2639] Rename task.lastException -> task.exception --- .../jackhuang/hmcl/game/LauncherHelper.java | 2 +- .../TaskExecutorDialogWizardDisplayer.java | 6 +++--- .../jackhuang/hmcl/upgrade/UpdateHandler.java | 3 +-- .../download/game/LibraryDownloadTask.java | 2 +- .../java/org/jackhuang/hmcl/task/Task.java | 16 +++++++-------- .../org/jackhuang/hmcl/task/TaskExecutor.java | 20 +++++++++---------- 6 files changed, 24 insertions(+), 25 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 4094deb795..f74ddf36a3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -213,7 +213,7 @@ public void onStop(boolean success, TaskExecutor executor) { // because onStop will be invoked if tasks fail when the executor service shut down. if (!Controllers.isStopped()) { launchingStepsPane.fireEvent(new DialogCloseEvent()); - Exception ex = executor.getLastException(); + Exception ex = executor.getException(); if (ex != null) { String message; if (ex instanceof CurseCompletionException) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 41119e2e82..62591dc7d2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -71,11 +71,11 @@ public void onStop(boolean success, TaskExecutor executor) { else if (!settings.containsKey("forbid_success_message")) Controllers.dialog(i18n("message.success"), null, MessageType.FINE, () -> onEnd()); } else { - if (executor.getLastException() == null) + if (executor.getException() == null) return; - String appendix = StringUtils.getStackTrace(executor.getLastException()); + String appendix = StringUtils.getStackTrace(executor.getException()); if (settings.get("failure_callback") instanceof WizardProvider.FailureCallback) - ((WizardProvider.FailureCallback)settings.get("failure_callback")).onFail(settings, executor.getLastException(), () -> onEnd()); + ((WizardProvider.FailureCallback)settings.get("failure_callback")).onFail(settings, executor.getException(), () -> onEnd()); else if (settings.get("failure_message") instanceof String) Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageType.ERROR, () -> onEnd()); else if (!settings.containsKey("forbid_failure_message")) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 1be18e5522..adf98e9e62 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -20,7 +20,6 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; import javafx.application.Platform; -import javafx.scene.layout.Region; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.task.Task; @@ -121,7 +120,7 @@ public static void updateFrom(RemoteVersion version) { } } else { - Throwable e = executor.getLastException(); + Exception e = executor.getException(); LOG.log(Level.WARNING, "Failed to update to " + version, e); Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageType.ERROR)); } 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 b9d5e92b27..8a4d08b2c6 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 @@ -91,7 +91,7 @@ public void execute() throws Exception { if (!isDependentsSucceeded()) { // Since FileDownloadTask wraps the actual exception with DownloadException. // We should extract it letting the error message clearer. - Throwable t = task.getLastException(); + Exception t = task.getException(); if (t instanceof DownloadException) throw new LibraryDownloadException(library, t.getCause()); else 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 292ae08f6c..638ef30137 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -73,14 +73,14 @@ void setState(TaskState state) { } // last exception - private Exception lastException; + private Exception exception; - public Exception getLastException() { - return lastException; + public Exception getException() { + return exception; } - void setLastException(Exception e) { - lastException = e; + void setException(Exception e) { + exception = e; } /** @@ -595,14 +595,14 @@ public Scheduler getScheduler() { @Override public void execute() throws Exception { - action.execute(isDependentsSucceeded(), Task.this.getLastException()); + action.execute(isDependentsSucceeded(), Task.this.getException()); if (!isDependentsSucceeded()) { setSignificance(TaskSignificance.MINOR); - if (Task.this.getLastException() == null) + if (Task.this.getException() == null) throw new CancellationException(); else - throw Task.this.getLastException(); + throw Task.this.getException(); } } 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 b7b5be421e..64aece34ae 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -33,7 +33,7 @@ public final class TaskExecutor { private final Task firstTask; private final List taskListeners = new LinkedList<>(); - private Exception lastException; + private Exception exception; private final AtomicInteger totTask = new AtomicInteger(0); private CompletableFuture future; @@ -45,8 +45,8 @@ public void addTaskListener(TaskListener taskListener) { taskListeners.add(taskListener); } - public Exception getLastException() { - return lastException; + public Exception getException() { + return exception; } public TaskExecutor start() { @@ -148,7 +148,7 @@ private CompletableFuture executeTask(Task task) { boolean isDependentsSucceeded = dependentsException == null; if (!isDependentsSucceeded && task.isRelyingOnDependents()) { - task.setLastException(dependentsException); + task.setException(dependentsException); rethrow(dependentsException); } @@ -174,7 +174,7 @@ private CompletableFuture executeTask(Task task) { if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) { Logging.LOG.severe("Subtasks failed for " + task.getName()); - task.setLastException(dependenciesException); + task.setException(dependenciesException); rethrow(dependenciesException); } @@ -193,18 +193,18 @@ private CompletableFuture executeTask(Task task) { throw new UncheckedThrowable(throwable); Exception e = throwable instanceof UncheckedException ? (Exception) throwable.getCause() : (Exception) throwable; if (e instanceof InterruptedException) { - task.setLastException(e); + task.setException(e); if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); } task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { - if (task.getLastException() == null) - task.setLastException(e); + if (task.getException() == null) + task.setException(e); } else { - task.setLastException(e); - lastException = e; + task.setException(e); + exception = e; if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); } From cae32cff4cbd4aecad5c6af25822b0be8d58d6ea Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 25 Feb 2019 23:59:21 +0800 Subject: [PATCH 0054/2639] remove isDependentSucceeded in whenComplete --- .../ui/account/AddAuthlibInjectorServerPane.java | 4 ++-- .../ui/download/VanillaInstallWizardProvider.java | 2 +- .../jackhuang/hmcl/ui/download/VersionsPage.java | 4 ++-- .../jackhuang/hmcl/ui/versions/ModListPage.java | 4 ++-- .../jackhuang/hmcl/ui/versions/WorldListPage.java | 4 ++-- .../hmcl/download/DefaultGameBuilder.java | 4 ++-- .../org/jackhuang/hmcl/task/SchedulerImpl.java | 10 +++++----- .../main/java/org/jackhuang/hmcl/task/Task.java | 15 +++++++++------ .../java/org/jackhuang/hmcl/util/TaskTest.java | 4 ++-- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index b37dbd39c5..02a3b25780 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,11 +106,11 @@ private void onAddNext() { Task.runAsync(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).whenComplete(Schedulers.javafx(), (isDependentSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), exception -> { addServerPane.setDisable(false); nextPane.hideSpinner(); - if (isDependentSucceeded) { + if (exception == null) { lblServerName.setText(serverBeingAdded.getName()); lblServerUrl.setText(serverBeingAdded.getUrl()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 4deceef5b4..86e1d2ada4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ private Task finishVersionDownloadingAsync(Map settings) { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().whenComplete(any -> profile.getRepository().refreshVersions()) .thenRun(Schedulers.javafx(), () -> profile.setSelectedVersion(name)); } 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 b23af41de2..d84338c49b 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 @@ -128,8 +128,8 @@ private List loadVersions() { @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentSucceeded, exception) -> { - if (isDependentSucceeded) { + executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete(exception -> { + if (exception == null) { List items = loadVersions(); Platform.runLater(() -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 1b9050e0b9..b987b2b38a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -91,9 +91,9 @@ public void loadMods(ModManager modManager) { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).whenComplete(Schedulers.javafx(), (list, isDependentSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (list, exception) -> { loadingProperty().set(false); - if (isDependentSucceeded) + if (exception == null) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { if (newValue != null && newValue.getUserData() == ModListPage.this) itemsProperty().setAll(list.stream().map(ModListPageSkin.ModInfoObject::new).collect(Collectors.toList())); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 4cbc160aec..8bfb39c0c5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -51,9 +51,9 @@ public void loadVersion(Profile profile, String id) { setLoading(true); Task.supplyAsync(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> { + .whenComplete(Schedulers.javafx(), (result, exception) -> { setLoading(false); - if (isDependentSucceeded) + if (exception == null) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); }).start(); } 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 c3d9994a69..d62ccf21d4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -68,8 +68,8 @@ public Task buildAsync() { libraryTask = libraryTask.thenCompose(dependencyManager.installLibraryAsync(remoteVersion)); return libraryTask; - }).whenComplete((isDependentSucceeded, exception) -> { - if (!isDependentSucceeded) + }).whenComplete(exception -> { + if (exception != null) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java index b5229ec8e4..38410b89c6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java @@ -19,9 +19,9 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; +import org.jetbrains.annotations.NotNull; /** * @@ -29,9 +29,9 @@ */ class SchedulerImpl extends Scheduler { - private final Consumer executor; + private final Executor executor; - public SchedulerImpl(Consumer executor) { + public SchedulerImpl(Executor executor) { this.executor = executor; } @@ -40,7 +40,7 @@ public Future schedule(ExceptionalRunnable block) { CountDownLatch latch = new CountDownLatch(1); AtomicReference wrapper = new AtomicReference<>(); - executor.accept(() -> { + executor.execute(() -> { try { block.run(); } catch (Exception e) { @@ -81,7 +81,7 @@ public Void get() throws InterruptedException, ExecutionException { } @Override - public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + public Void get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (!latch.await(timeout, unit)) throw new TimeoutException(); return getImpl(); 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 638ef30137..22f893ee1f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -595,7 +595,10 @@ public Scheduler getScheduler() { @Override public void execute() throws Exception { - action.execute(isDependentsSucceeded(), Task.this.getException()); + if (isDependentsSucceeded() != (Task.this.getException() == null)) + throw new AssertionError("When dependents succeeded, Task.exception must be nonnull."); + + action.execute(Task.this.getException()); if (!isDependentsSucceeded()) { setSignificance(TaskSignificance.MINOR); @@ -634,7 +637,7 @@ public boolean isRelyingOnDependents() { * @return the new Task */ public Task whenComplete(Scheduler scheduler, FinalizedCallbackWithResult action) { - return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception))); + return whenComplete(scheduler, (exception -> action.execute(getResult(), exception))); } /** @@ -653,8 +656,8 @@ public Task whenComplete(Scheduler scheduler, FinalizedCallbackWithResult< * @return the new Task */ public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { - return whenComplete(scheduler, (isDependentSucceeded, exception) -> { - if (isDependentSucceeded) { + return whenComplete(scheduler, exception -> { + if (exception == null) { if (success != null) try { success.run(); @@ -805,11 +808,11 @@ public enum TaskState { } public interface FinalizedCallback { - void execute(boolean isDependentSucceeded, Exception exception) throws Exception; + void execute(Exception exception) throws Exception; } public interface FinalizedCallbackWithResult { - void execute(T result, boolean isDependentSucceeded, Exception exception) throws Exception; + void execute(T result, Exception exception) throws Exception; } private static String getCaller() { diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java index 5520461bbc..1704f9c140 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java @@ -11,8 +11,8 @@ public void testWhenComplete() { Task.allOf(Task.runAsync(() -> { throw new Exception(); })) - )).whenComplete(((isDependentSucceeded, exception) -> { - Assert.assertFalse(isDependentSucceeded); + )).whenComplete((exception -> { + Assert.assertFalse(exception == null); })).test(); } } From 15a75a69b39fee1c5206aa90200c7cad3048b112 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 26 Feb 2019 08:17:46 +0800 Subject: [PATCH 0055/2639] Fix exception handling --- .../org/jackhuang/hmcl/task/TaskExecutor.java | 97 +++++++++---------- .../org/jackhuang/hmcl/util/TaskTest.java | 47 +++++++-- 2 files changed, 86 insertions(+), 58 deletions(-) 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 64aece34ae..ce7392101f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -58,7 +58,7 @@ public TaskExecutor start() { return success; }) .exceptionally(e -> { - Lang.handleUncaughtException(e instanceof UncheckedThrowable ? e.getCause() : e); + Lang.handleUncaughtException(resolveException(e)); return false; }); return this; @@ -101,11 +101,15 @@ private CompletableFuture executeTasks(Collection> tasks) { }) .thenApplyAsync(unused -> (Exception) null) .exceptionally(throwable -> { - if (throwable instanceof Exception) { - return (Exception) throwable; + if (!(throwable instanceof CompletionException)) + throw new AssertionError(); + + Throwable resolved = resolveException(throwable); + if (resolved instanceof Exception) { + return (Exception) resolved; } else { // If an error occurred, we just rethrow it. - throw new UncheckedThrowable(throwable); + throw (CompletionException) throwable; } }); } @@ -117,20 +121,15 @@ private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runna private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runnable, Runnable finalize) { try { scheduler.schedule(runnable).get(); - } catch (ExecutionException e) { - if (e.getCause() instanceof Exception) - rethrow(e.getCause()); - else - throw new UncheckedException(e); - } catch (InterruptedException e) { - throw new UncheckedException(e); + } catch (ExecutionException | InterruptedException e) { + throw new CompletionException(e); } finally { if (finalize != null) finalize.run(); } } - private CompletableFuture executeTask(Task task) { + private CompletableFuture executeTask(Task task) { return CompletableFuture.completedFuture(null).thenComposeAsync(unused -> { task.setState(Task.TaskState.READY); @@ -188,33 +187,36 @@ private CompletableFuture executeTask(Task task) { task.setState(Task.TaskState.SUCCEEDED); return null; - }).exceptionally(throwable -> { - if (!(throwable instanceof Exception)) - throw new UncheckedThrowable(throwable); - Exception e = throwable instanceof UncheckedException ? (Exception) throwable.getCause() : (Exception) throwable; - if (e instanceof InterruptedException) { - task.setException(e); - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); - } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { - if (task.getException() == null) + }).thenApplyAsync(unused -> null).exceptionally(throwable -> { + if (!(throwable instanceof CompletionException)) + throw new AssertionError(); + + Throwable resolved = resolveException(throwable); + if (resolved instanceof Exception) { + Exception e = (Exception) resolved; + if (e instanceof InterruptedException) { + task.setException(e); + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); + } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { + task.setException(e); + } else { task.setException(e); - } else { - task.setException(e); - exception = e; - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + exception = e; + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } - task.setState(Task.TaskState.FAILED); + task.setState(Task.TaskState.FAILED); + } - throw new UncheckedException(e); + throw (CompletionException) throwable; // rethrow error }); } @@ -222,27 +224,20 @@ public int getRunningTasks() { return totTask.get(); } - private static class UncheckedException extends RuntimeException { - - UncheckedException(Exception exception) { - super(exception); - } - } - - private static class UncheckedThrowable extends RuntimeException { - - UncheckedThrowable(Throwable throwable) { - super(throwable); - } + private static Throwable resolveException(Throwable e) { + if (e instanceof ExecutionException || e instanceof CompletionException) + return resolveException(e.getCause()); + else + return e; } private static void rethrow(Throwable e) { - if (e instanceof RuntimeException) { // including UncheckedException and UncheckedThrowable + if (e instanceof ExecutionException || e instanceof CompletionException) { // including UncheckedException and UncheckedThrowable + rethrow(e.getCause()); + } else if (e instanceof RuntimeException) { throw (RuntimeException) e; - } else if (e instanceof Exception) { - throw new UncheckedException((Exception) e); } else { - throw new UncheckedThrowable(e); + throw new CompletionException(e); } } } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java index 1704f9c140..edeba03df5 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java @@ -4,15 +4,48 @@ import org.junit.Assert; import org.junit.Test; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + public class TaskTest { + /** + * TaskExecutor will not catch error and will be thrown to global handler. + */ @Test - public void testWhenComplete() { - Task.composeAsync(() -> Task.allOf( + public void expectErrorUncaught() { + AtomicReference throwable = new AtomicReference<>(); + Thread.setDefaultUncaughtExceptionHandler((t, e) -> throwable.set(e)); + Assert.assertFalse(Task.composeAsync(() -> Task.allOf( Task.allOf(Task.runAsync(() -> { - throw new Exception(); + throw new Error(); })) - )).whenComplete((exception -> { - Assert.assertFalse(exception == null); - })).test(); + )).whenComplete(Assert::assertNull).test()); + + Assert.assertTrue(throwable.get() instanceof Error); + } + + /** + * + */ + @Test + public void testWhenComplete() { + Assert.assertFalse(Task.supplyAsync(() -> { + throw new IllegalStateException(); + }).whenComplete(exception -> { + Assert.assertTrue(exception instanceof IllegalStateException); + }).test()); + } + + @Test + public void testWithCompose() { + AtomicBoolean bool = new AtomicBoolean(); + boolean success = Task.supplyAsync(() -> { + throw new IllegalStateException(); + }).withRun(() -> { + bool.set(true); + }).test(); + + Assert.assertTrue(success); + Assert.assertTrue(bool.get()); } -} +} \ No newline at end of file From 3c958d06c837f56ffb19e5a1775411cef19b98a2 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 26 Feb 2019 11:39:38 +0800 Subject: [PATCH 0056/2639] Replace scheduler to executor --- .../jackhuang/hmcl/game/LauncherHelper.java | 2 +- .../MultiMCInstallVersionSettingTask.java | 6 +- .../org/jackhuang/hmcl/setting/Accounts.java | 4 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 7 +- .../java/org/jackhuang/hmcl/task/GetTask.java | 7 +- .../hmcl/task/SchedulerExecutorService.java | 45 ---- .../jackhuang/hmcl/task/SchedulerImpl.java | 92 -------- .../org/jackhuang/hmcl/task/Schedulers.java | 54 +---- .../java/org/jackhuang/hmcl/task/Task.java | 167 +++++++-------- .../org/jackhuang/hmcl/task/TaskExecutor.java | 198 ++++++++++-------- .../org/jackhuang/hmcl/util/TaskTest.java | 30 ++- 11 files changed, 235 insertions(+), 377 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerExecutorService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.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 f74ddf36a3..69706a64b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -102,7 +102,7 @@ public void launch() { try { checkGameState(profile, setting, version, () -> { Controllers.dialog(launchingStepsPane); - Schedulers.newThread().schedule(this::launch0); + Schedulers.newThread().execute(this::launch0); }); } catch (InterruptedException ignore) { } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java index 31a3bece93..70f0cedad3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java @@ -25,6 +25,7 @@ import org.jackhuang.hmcl.task.Task; import java.util.Objects; +import java.util.concurrent.Executor; public final class MultiMCInstallVersionSettingTask extends Task { private final Profile profile; @@ -35,11 +36,8 @@ public MultiMCInstallVersionSettingTask(Profile profile, MultiMCInstanceConfigur this.profile = profile; this.manifest = manifest; this.version = version; - } - @Override - public Scheduler getScheduler() { - return Schedulers.javafx(); + setExecutor(Schedulers.javafx()); } @Override 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 c2097f290c..3ec9f85753 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -197,7 +197,7 @@ static void init() { Account selected = selectedAccount.get(); if (selected != null) { - Schedulers.io().schedule(() -> { + Schedulers.io().execute(() -> { try { selected.logIn(); } catch (AuthenticationException e) { @@ -209,7 +209,7 @@ static void init() { for (AuthlibInjectorServer server : config().getAuthlibInjectorServers()) { if (selected instanceof AuthlibInjectorAccount && ((AuthlibInjectorAccount) selected).getServer() == server) continue; - Schedulers.io().schedule(() -> { + Schedulers.io().execute(() -> { try { server.fetchMetadataResponse(); } catch (IOException e) { 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 670c4b6d5a..8d4b2cb5dd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -37,6 +37,7 @@ import java.nio.file.Path; import java.security.MessageDigest; import java.util.Optional; +import java.util.concurrent.Executor; import java.util.logging.Level; import static java.util.Objects.requireNonNull; @@ -124,6 +125,7 @@ public FileDownloadTask(URL url, File file, IntegrityCheck integrityCheck, int r this.retry = retry; setName(file.getName()); + setExecutor(Schedulers.io()); } private void closeFiles() { @@ -145,11 +147,6 @@ private void closeFiles() { stream = null; } - @Override - public Scheduler getScheduler() { - return Schedulers.io(); - } - public EventManager> getOnFailed() { return onFailed; } 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 24fd5738b8..6787b42d9e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -30,6 +30,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; +import java.util.concurrent.Executor; import java.util.logging.Level; import static java.nio.charset.StandardCharsets.UTF_8; @@ -59,11 +60,7 @@ public GetTask(URL url, Charset charset, int retry) { this.retry = retry; setName(url.toString()); - } - - @Override - public Scheduler getScheduler() { - return Schedulers.io(); + setExecutor(Schedulers.io()); } public GetTask setCacheRepository(CacheRepository repository) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerExecutorService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerExecutorService.java deleted file mode 100644 index f1b9da7f5e..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerExecutorService.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; - -/** - * - * @author huangyuhui - */ -class SchedulerExecutorService extends Scheduler { - - private final ExecutorService executorService; - - public SchedulerExecutorService(ExecutorService executorService) { - this.executorService = executorService; - } - - @Override - public Future schedule(ExceptionalRunnable block) { - if (executorService.isShutdown() || executorService.isTerminated()) - return Schedulers.NONE.schedule(block); - else - return executorService.submit(block.toCallable()); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java deleted file mode 100644 index 38410b89c6..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SchedulerImpl.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; - -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; -import org.jetbrains.annotations.NotNull; - -/** - * - * @author huangyuhui - */ -class SchedulerImpl extends Scheduler { - - private final Executor executor; - - public SchedulerImpl(Executor executor) { - this.executor = executor; - } - - @Override - public Future schedule(ExceptionalRunnable block) { - CountDownLatch latch = new CountDownLatch(1); - AtomicReference wrapper = new AtomicReference<>(); - - executor.execute(() -> { - try { - block.run(); - } catch (Exception e) { - wrapper.set(e); - } finally { - latch.countDown(); - } - Thread.interrupted(); // clear the `interrupted` flag to prevent from interrupting EventDispatch thread. - }); - - return new Future() { - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return latch.getCount() == 0; - } - - private Void getImpl() throws ExecutionException { - Exception e = wrapper.get(); - if (e != null) - throw new ExecutionException(e); - return null; - } - - @Override - public Void get() throws InterruptedException, ExecutionException { - latch.await(); - return getImpl(); - } - - @Override - public Void get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (!latch.await(timeout, unit)) - throw new TimeoutException(); - return getImpl(); - } - }; - } - -} 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 57f2ac639b..0edf531d46 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -17,8 +17,10 @@ */ package org.jackhuang.hmcl.task; +import javafx.application.Platform; import org.jackhuang.hmcl.util.Logging; +import javax.swing.*; import java.util.concurrent.*; /** @@ -32,7 +34,7 @@ private Schedulers() { private static volatile ExecutorService CACHED_EXECUTOR; - private static synchronized ExecutorService getCachedExecutorService() { + public static synchronized Executor newThread() { if (CACHED_EXECUTOR == null) CACHED_EXECUTOR = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), Executors.defaultThreadFactory()); @@ -42,7 +44,7 @@ private static synchronized ExecutorService getCachedExecutorService() { private static volatile ExecutorService IO_EXECUTOR; - private static synchronized ExecutorService getIOExecutorService() { + public static synchronized Executor io() { if (IO_EXECUTOR == null) IO_EXECUTOR = Executors.newFixedThreadPool(6, runnable -> { Thread thread = Executors.defaultThreadFactory().newThread(runnable); @@ -55,7 +57,7 @@ private static synchronized ExecutorService getIOExecutorService() { private static volatile ExecutorService SINGLE_EXECUTOR; - private static synchronized ExecutorService getSingleExecutorService() { + public static synchronized Executor computation() { if (SINGLE_EXECUTOR == null) SINGLE_EXECUTOR = Executors.newSingleThreadExecutor(runnable -> { Thread thread = Executors.defaultThreadFactory().newThread(runnable); @@ -66,54 +68,18 @@ private static synchronized ExecutorService getSingleExecutorService() { return SINGLE_EXECUTOR; } - private static final Scheduler IMMEDIATE = new SchedulerImpl(Runnable::run); - - public static Scheduler immediate() { - return IMMEDIATE; - } - - private static Scheduler NEW_THREAD; - - public static synchronized Scheduler newThread() { - if (NEW_THREAD == null) - NEW_THREAD = new SchedulerExecutorService(getCachedExecutorService()); - return NEW_THREAD; + public static Executor javafx() { + return Platform::runLater; } - private static Scheduler IO; - - public static synchronized Scheduler io() { - if (IO == null) - IO = new SchedulerExecutorService(getIOExecutorService()); - return IO; - } - - private static Scheduler COMPUTATION; - - public static synchronized Scheduler computation() { - if (COMPUTATION == null) - COMPUTATION = new SchedulerExecutorService(getSingleExecutorService()); - return COMPUTATION; + public static Executor swing() { + return SwingUtilities::invokeLater; } - private static final Scheduler JAVAFX = new SchedulerImpl(javafx.application.Platform::runLater); - - public static Scheduler javafx() { - return JAVAFX; - } - - private static final Scheduler SWING = new SchedulerImpl(javax.swing.SwingUtilities::invokeLater); - - public static Scheduler swing() { - return SWING; - } - - public static synchronized Scheduler defaultScheduler() { + public static Executor defaultScheduler() { return newThread(); } - static final Scheduler NONE = new SchedulerImpl(any -> {}); - public static synchronized void shutdown() { Logging.LOG.info("Shutting down executor services."); 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 22f893ee1f..10e54b032e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.logging.Level; @@ -57,37 +58,44 @@ public final TaskSignificance getSignificance() { return significance; } - public void setSignificance(TaskSignificance significance) { + public final void setSignificance(TaskSignificance significance) { this.significance = significance; } // state private TaskState state = TaskState.READY; - public TaskState getState() { + public final TaskState getState() { return state; } - void setState(TaskState state) { + final void setState(TaskState state) { this.state = state; } // last exception private Exception exception; - public Exception getException() { + public final Exception getException() { return exception; } - void setException(Exception e) { + final void setException(Exception e) { exception = e; } + private Executor executor = Schedulers.defaultScheduler(); + /** - * The scheduler that decides how this task runs. + * The executor that decides how this task runs. */ - public Scheduler getScheduler() { - return Schedulers.defaultScheduler(); + public final Executor getExecutor() { + return executor; + } + + public final Task setExecutor(Executor executor) { + this.executor = executor; + return this; } // dependents succeeded @@ -142,6 +150,14 @@ public Task setName(String name) { return this; } + @Override + public String toString() { + if (getClass().getName().equals(getName())) + return getName(); + else + return getClass().getName() + "[" + getName() + "]"; + } + // result private T result; private Consumer resultConsumer; @@ -314,7 +330,7 @@ public final boolean test() { /** * Returns a new Task that, when this task completes - * normally, is executed using the default Scheduler, with this + * normally, is executed using the default Executor, with this * task's result as the argument to the supplied function. * * @param fn the function to use to compute the value of the returned Task @@ -327,36 +343,36 @@ public Task thenApply(ExceptionalFunction f /** * Returns a new Task that, when this task completes - * normally, is executed using the supplied Scheduler, with this + * normally, is executed using the supplied Executor, with this * task's result as the argument to the supplied function. * - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @param fn the function to use to compute the value of the returned Task * @param the function's return type * @return the new Task */ - public Task thenApply(Scheduler scheduler, ExceptionalFunction fn) { - return thenApply(getCaller(), scheduler, fn); + public Task thenApply(Executor executor, ExceptionalFunction fn) { + return thenApply(getCaller(), executor, fn); } /** * Returns a new Task that, when this task completes - * normally, is executed using the supplied Scheduler, with this + * normally, is executed using the supplied Executor, with this * task's result as the argument to the supplied function. * * @param name the name of this new Task for displaying - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @param fn the function to use to compute the value of the returned Task * @param the function's return type * @return the new Task */ - public Task thenApply(String name, Scheduler scheduler, ExceptionalFunction fn) { - return new UniApply<>(name, scheduler, fn); + public Task thenApply(String name, Executor executor, ExceptionalFunction fn) { + return new UniApply<>(fn).setExecutor(executor).setName(name); } /** * Returns a new Task that, when this task completes - * normally, is executed using the default Scheduler, with this + * normally, is executed using the default Executor, with this * task's result as the argument to the supplied action. * * @param action the action to perform before completing the @@ -369,29 +385,29 @@ public Task thenAccept(ExceptionalConsumer act /** * Returns a new Task that, when this task completes - * normally, is executed using the supplied Scheduler, with this + * normally, is executed using the supplied Executor, with this * task's result as the argument to the supplied action. * * @param action the action to perform before completing the returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task thenAccept(Scheduler scheduler, ExceptionalConsumer action) { - return thenAccept(getCaller(), scheduler, action); + public Task thenAccept(Executor executor, ExceptionalConsumer action) { + return thenAccept(getCaller(), executor, action); } /** * Returns a new Task that, when this task completes - * normally, is executed using the supplied Scheduler, with this + * normally, is executed using the supplied Executor, with this * task's result as the argument to the supplied action. * * @param name the name of this new Task for displaying * @param action the action to perform before completing the returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task thenAccept(String name, Scheduler scheduler, ExceptionalConsumer action) { - return thenApply(name, scheduler, result -> { + public Task thenAccept(String name, Executor executor, ExceptionalConsumer action) { + return thenApply(name, executor, result -> { action.accept(result); return null; }); @@ -399,7 +415,7 @@ public Task thenAccept(String name, Scheduler schedu /** * Returns a new Task that, when this task completes - * normally, executes the given action using the default Scheduler. + * normally, executes the given action using the default Executor. * * @param action the action to perform before completing the * returned Task @@ -411,29 +427,29 @@ public Task thenRun(ExceptionalRunnable action) { /** * Returns a new Task that, when this task completes - * normally, executes the given action using the supplied Scheduler. + * normally, executes the given action using the supplied Executor. * * @param action the action to perform before completing the * returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task thenRun(Scheduler scheduler, ExceptionalRunnable action) { - return thenRun(getCaller(), scheduler, action); + public Task thenRun(Executor executor, ExceptionalRunnable action) { + return thenRun(getCaller(), executor, action); } /** * Returns a new Task that, when this task completes - * normally, executes the given action using the supplied Scheduler. + * normally, executes the given action using the supplied Executor. * * @param name the name of this new Task for displaying * @param action the action to perform before completing the * returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task thenRun(String name, Scheduler scheduler, ExceptionalRunnable action) { - return thenApply(name, scheduler, ignore -> { + public Task thenRun(String name, Executor executor, ExceptionalRunnable action) { + return thenApply(name, executor, ignore -> { action.run(); return null; }); @@ -441,7 +457,7 @@ public Task thenRun(String name, Scheduler scheduler /** * Returns a new Task that, when this task completes - * normally, is executed using the default Scheduler. + * normally, is executed using the default Executor. * * @param fn the function to use to compute the value of the returned Task * @param the function's return type @@ -453,7 +469,7 @@ public final Task thenSupply(Callable fn) { /** * Returns a new Task that, when this task completes - * normally, is executed using the default Scheduler. + * normally, is executed using the default Executor. * * @param name the name of this new Task for displaying * @param fn the function to use to compute the value of the returned Task @@ -511,7 +527,7 @@ public final Task withCompose(ExceptionalSupplier Task withRun(ExceptionalRunnable action) { /** * Returns a new Task that, when this task completes - * normally, executes the given action using the supplied Scheduler. + * normally, executes the given action using the supplied Executor. * * @param action the action to perform before completing the * returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task withRun(Scheduler scheduler, ExceptionalRunnable action) { - return withRun(getCaller(), scheduler, action); + public Task withRun(Executor executor, ExceptionalRunnable action) { + return withRun(getCaller(), executor, action); } /** * Returns a new Task that, when this task completes - * normally, executes the given action using the supplied Scheduler. + * normally, executes the given action using the supplied Executor. * * @param name the name of this new Task for displaying * @param action the action to perform before completing the * returned Task - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public Task withRun(String name, Scheduler scheduler, ExceptionalRunnable action) { - return new UniCompose<>(() -> Task.runAsync(name, scheduler, action), false); + public Task withRun(String name, Executor executor, ExceptionalRunnable action) { + return new UniCompose<>(() -> Task.runAsync(name, executor, action), false); } /** @@ -579,20 +595,15 @@ public final Task whenComplete(FinalizedCallback action) { * with this exception unless this task also completed exceptionally. * * @param action the action to perform - * @param scheduler the executor to use for asynchronous execution + * @param executor the executor to use for asynchronous execution * @return the new Task */ - public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + public final Task whenComplete(Executor executor, FinalizedCallback action) { return new Task() { { setSignificance(TaskSignificance.MODERATE); } - @Override - public Scheduler getScheduler() { - return scheduler; - } - @Override public void execute() throws Exception { if (isDependentsSucceeded() != (Task.this.getException() == null)) @@ -618,7 +629,7 @@ public Collection> getDependents() { public boolean isRelyingOnDependents() { return false; } - }.setName(getCaller()); + }.setExecutor(executor).setName(getCaller()); } /** @@ -636,8 +647,8 @@ public boolean isRelyingOnDependents() { * @param action the action to perform * @return the new Task */ - public Task whenComplete(Scheduler scheduler, FinalizedCallbackWithResult action) { - return whenComplete(scheduler, (exception -> action.execute(getResult(), exception))); + public Task whenComplete(Executor executor, FinalizedCallbackWithResult action) { + return whenComplete(executor, (exception -> action.execute(getResult(), exception))); } /** @@ -655,8 +666,8 @@ public Task whenComplete(Scheduler scheduler, FinalizedCallbackWithResult< * @param failure the action to perform when this task exceptionally returned * @return the new Task */ - public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { - return whenComplete(scheduler, exception -> { + public final Task whenComplete(Executor executor, ExceptionalRunnable success, ExceptionalConsumer failure) { + return whenComplete(executor, exception -> { if (exception == null) { if (success != null) try { @@ -688,8 +699,8 @@ public final Task whenComplet * @param failure the action to perform when this task exceptionally returned * @return the new Task */ - public Task whenComplete(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { - return whenComplete(scheduler, () -> success.accept(getResult()), failure); + public Task whenComplete(Executor executor, ExceptionalConsumer success, ExceptionalConsumer failure) { + return whenComplete(executor, () -> success.accept(getResult()), failure); } public static Task runAsync(ExceptionalRunnable closure) { @@ -700,12 +711,12 @@ public static Task runAsync(String name, ExceptionalRunnable closure) { return runAsync(name, Schedulers.defaultScheduler(), closure); } - public static Task runAsync(Scheduler scheduler, ExceptionalRunnable closure) { - return runAsync(getCaller(), scheduler, closure); + public static Task runAsync(Executor executor, ExceptionalRunnable closure) { + return runAsync(getCaller(), executor, closure); } - public static Task runAsync(String name, Scheduler scheduler, ExceptionalRunnable closure) { - return new SimpleTask<>(closure.toCallable(), scheduler).setName(name); + public static Task runAsync(String name, Executor executor, ExceptionalRunnable closure) { + return new SimpleTask<>(closure.toCallable()).setExecutor(executor).setName(name); } public static Task composeAsync(ExceptionalSupplier, ?> fn) { @@ -730,16 +741,16 @@ public static Task supplyAsync(Callable callable) { return supplyAsync(getCaller(), callable); } - public static Task supplyAsync(Scheduler scheduler, Callable callable) { - return supplyAsync(getCaller(), scheduler, callable); + public static Task supplyAsync(Executor executor, Callable callable) { + return supplyAsync(getCaller(), executor, callable); } public static Task supplyAsync(String name, Callable callable) { return supplyAsync(name, Schedulers.defaultScheduler(), callable); } - public static Task supplyAsync(String name, Scheduler scheduler, Callable callable) { - return new SimpleTask<>(callable, scheduler).setName(name); + public static Task supplyAsync(String name, Executor executor, Callable callable) { + return new SimpleTask<>(callable).setExecutor(executor).setName(name); } /** @@ -822,16 +833,9 @@ private static String getCaller() { private static final class SimpleTask extends Task { private final Callable callable; - private final Scheduler scheduler; - SimpleTask(Callable callable, Scheduler scheduler) { + SimpleTask(Callable callable) { this.callable = callable; - this.scheduler = scheduler; - } - - @Override - public Scheduler getScheduler() { - return scheduler; } @Override @@ -841,14 +845,10 @@ public void execute() throws Exception { } private class UniApply extends Task { - private final Scheduler scheduler; private final ExceptionalFunction callable; - UniApply(String name, Scheduler scheduler, ExceptionalFunction callable) { - this.scheduler = scheduler; + UniApply(ExceptionalFunction callable) { this.callable = callable; - - setName(name); } @Override @@ -856,11 +856,6 @@ public Collection> getDependents() { return Collections.singleton(Task.this); } - @Override - public Scheduler getScheduler() { - return scheduler; - } - @Override public void execute() throws Exception { setResult(callable.apply(Task.this.getResult())); 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 ce7392101f..e3393c7079 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -54,6 +54,12 @@ public TaskExecutor start() { future = executeTasks(Collections.singleton(firstTask)) .thenApplyAsync(exception -> { boolean success = exception == null; + + if (!success) { + // We log exception stacktrace because some of exceptions occurred because of bugs. + Logging.LOG.log(Level.WARNING, "An exception occurred in task execution", exception); + } + taskListeners.forEach(it -> it.onStop(success, this)); return success; }) @@ -71,6 +77,7 @@ public boolean test() { } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException | CancellationException e) { + e.printStackTrace(); } return false; } @@ -114,110 +121,113 @@ private CompletableFuture executeTasks(Collection> tasks) { }); } - private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runnable) { - scheduleTo(scheduler, runnable, null); - } - - private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable runnable, Runnable finalize) { - try { - scheduler.schedule(runnable).get(); - } catch (ExecutionException | InterruptedException e) { - throw new CompletionException(e); - } finally { - if (finalize != null) - finalize.run(); - } - } - private CompletableFuture executeTask(Task task) { - return CompletableFuture.completedFuture(null).thenComposeAsync(unused -> { - task.setState(Task.TaskState.READY); - - if (task.getSignificance().shouldLog()) - Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); - - taskListeners.forEach(it -> it.onReady(task)); - - if (task.doPreExecute()) { - scheduleTo(task.getScheduler(), task::preExecute); - } + return CompletableFuture.completedFuture(null) + .thenComposeAsync(unused -> { + task.setState(Task.TaskState.READY); - return executeTasks(task.getDependents()); - }).thenComposeAsync(dependentsException -> { - boolean isDependentsSucceeded = dependentsException == null; + if (task.getSignificance().shouldLog()) + Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); - if (!isDependentsSucceeded && task.isRelyingOnDependents()) { - task.setException(dependentsException); - rethrow(dependentsException); - } + taskListeners.forEach(it -> it.onReady(task)); - if (isDependentsSucceeded) - task.setDependentsSucceeded(); + if (task.doPreExecute()) { + return CompletableFuture.runAsync(wrap(task::preExecute), task.getExecutor()); + } else { + return CompletableFuture.completedFuture(null); + } + }) + .thenComposeAsync(unused -> { + return executeTasks(task.getDependents()); + }) + .thenComposeAsync(dependentsException -> { + boolean isDependentsSucceeded = dependentsException == null; - scheduleTo(task.getScheduler(), () -> { - task.setState(Task.TaskState.RUNNING); - taskListeners.forEach(it -> it.onRunning(task)); - task.execute(); - }, () -> task.setState(Task.TaskState.EXECUTED)); + if (!isDependentsSucceeded && task.isRelyingOnDependents()) { + task.setException(dependentsException); + rethrow(dependentsException); + } - return executeTasks(task.getDependencies()); - }).thenApplyAsync(dependenciesException -> { - boolean isDependenciesSucceeded = dependenciesException == null; + if (isDependentsSucceeded) + task.setDependentsSucceeded(); + + return CompletableFuture.runAsync(wrap(() -> { + task.setState(Task.TaskState.RUNNING); + taskListeners.forEach(it -> it.onRunning(task)); + task.execute(); + }), task.getExecutor()).whenComplete((unused, throwable) -> { + task.setState(Task.TaskState.EXECUTED); + rethrow(throwable); + }); + }) + .thenComposeAsync(unused -> { + return executeTasks(task.getDependencies()); + }) + .thenComposeAsync(dependenciesException -> { + boolean isDependenciesSucceeded = dependenciesException == null; - if (isDependenciesSucceeded) - task.setDependenciesSucceeded(); + if (isDependenciesSucceeded) + task.setDependenciesSucceeded(); - if (task.doPostExecute()) { - scheduleTo(task.getScheduler(), task::postExecute); - } + if (task.doPostExecute()) { + return CompletableFuture.runAsync(wrap(task::postExecute), task.getExecutor()) + .thenApply(unused -> dependenciesException); + } else { + return CompletableFuture.completedFuture(dependenciesException); + } + }) + .thenApplyAsync(dependenciesException -> { + boolean isDependenciesSucceeded = dependenciesException == null; - if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) { - Logging.LOG.severe("Subtasks failed for " + task.getName()); - task.setException(dependenciesException); - rethrow(dependenciesException); - } + if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) { + Logging.LOG.severe("Subtasks failed for " + task.getName()); + task.setException(dependenciesException); + rethrow(dependenciesException); + } - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); - } + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); + } - task.onDone().fireEvent(new TaskEvent(this, task, false)); - taskListeners.forEach(it -> it.onFinished(task)); + task.onDone().fireEvent(new TaskEvent(this, task, false)); + taskListeners.forEach(it -> it.onFinished(task)); - task.setState(Task.TaskState.SUCCEEDED); + task.setState(Task.TaskState.SUCCEEDED); - return null; - }).thenApplyAsync(unused -> null).exceptionally(throwable -> { - if (!(throwable instanceof CompletionException)) - throw new AssertionError(); + return null; + }) + .thenApplyAsync(unused -> null) + .exceptionally(throwable -> { + if (!(throwable instanceof CompletionException)) + throw new AssertionError(); - Throwable resolved = resolveException(throwable); - if (resolved instanceof Exception) { - Exception e = (Exception) resolved; - if (e instanceof InterruptedException) { - task.setException(e); - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); - } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { - task.setException(e); - } else { - task.setException(e); - exception = e; - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + Throwable resolved = resolveException(throwable); + if (resolved instanceof Exception) { + Exception e = (Exception) resolved; + if (e instanceof InterruptedException) { + task.setException(e); + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); + } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { + task.setException(e); + } else { + task.setException(e); + exception = e; + if (task.getSignificance().shouldLog()) { + Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); + } + task.onDone().fireEvent(new TaskEvent(this, task, true)); + taskListeners.forEach(it -> it.onFailed(task, e)); + } + + task.setState(Task.TaskState.FAILED); } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } - task.setState(Task.TaskState.FAILED); - } - - throw (CompletionException) throwable; // rethrow error - }); + throw (CompletionException) throwable; // rethrow error + }); } public int getRunningTasks() { @@ -232,6 +242,8 @@ private static Throwable resolveException(Throwable e) { } private static void rethrow(Throwable e) { + if (e == null) + return; if (e instanceof ExecutionException || e instanceof CompletionException) { // including UncheckedException and UncheckedThrowable rethrow(e.getCause()); } else if (e instanceof RuntimeException) { @@ -240,4 +252,14 @@ private static void rethrow(Throwable e) { throw new CompletionException(e); } } + + private static Runnable wrap(ExceptionalRunnable runnable) { + return () -> { + try { + runnable.run(); + } catch (Exception e) { + rethrow(e); + } + }; + } } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java index edeba03df5..b432dc1f17 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java @@ -1,6 +1,9 @@ package org.jackhuang.hmcl.util; +import javafx.embed.swing.JFXPanel; +import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.platform.JavaVersion; import org.junit.Assert; import org.junit.Test; @@ -21,7 +24,7 @@ public void expectErrorUncaught() { })) )).whenComplete(Assert::assertNull).test()); - Assert.assertTrue(throwable.get() instanceof Error); + Assert.assertTrue("Error has not been thrown to uncaught exception handler", throwable.get() instanceof Error); } /** @@ -29,11 +32,13 @@ public void expectErrorUncaught() { */ @Test public void testWhenComplete() { - Assert.assertFalse(Task.supplyAsync(() -> { + boolean result = Task.supplyAsync(() -> { throw new IllegalStateException(); }).whenComplete(exception -> { Assert.assertTrue(exception instanceof IllegalStateException); - }).test()); + }).test(); + + Assert.assertFalse("Task should fail at this case", result); } @Test @@ -45,7 +50,22 @@ public void testWithCompose() { bool.set(true); }).test(); - Assert.assertTrue(success); - Assert.assertTrue(bool.get()); + Assert.assertTrue("Task should success because withRun will ignore previous exception", success); + Assert.assertTrue("withRun should be executed", bool.get()); + } + + @Test + public void testThenAccept() { + new JFXPanel(); // init JavaFX Toolkit + AtomicBoolean flag = new AtomicBoolean(); + boolean result = Task.supplyAsync(JavaVersion::fromCurrentEnvironment) + .thenAccept(Schedulers.javafx(), javaVersion -> { + flag.set(true); + Assert.assertEquals(javaVersion, JavaVersion.fromCurrentEnvironment()); + }) + .test(); + + Assert.assertTrue("Task does not succeed", result); + Assert.assertTrue("ThenAccept has not been executed", flag.get()); } } \ No newline at end of file From d9a336e50b9e4babd926aeffc0f12d2c98c3dd81 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 26 Feb 2019 13:29:09 +0800 Subject: [PATCH 0057/2639] Remove redundant codes --- .../jackhuang/hmcl/game/LauncherHelper.java | 6 +- .../MultiMCInstallVersionSettingTask.java | 2 - .../java/org/jackhuang/hmcl/ui/MainPage.java | 1 - .../hmcl/ui/account/AccountListItemSkin.java | 1 - .../hmcl/ui/construct/IconedItem.java | 1 - .../hmcl/ui/decorator/DecoratorSkin.java | 2 - .../hmcl/ui/profile/ProfilePage.java | 3 - .../hmcl/ui/versions/InstallerListPage.java | 1 - .../jackhuang/hmcl/ui/versions/Versions.java | 1 - .../ui/wizard/DefaultWizardDisplayer.java | 1 - .../jackhuang/hmcl/upgrade/UpdateHandler.java | 1 + .../download/AbstractDependencyManager.java | 2 - .../hmcl/download/MojangDownloadProvider.java | 1 - .../java/org/jackhuang/hmcl/game/World.java | 1 - .../org/jackhuang/hmcl/task/Scheduler.java | 38 --------- .../org/jackhuang/hmcl/task/TaskExecutor.java | 31 +++----- .../org/jackhuang/hmcl/task/TaskListener.java | 42 ++++++++-- .../jackhuang/hmcl/util/AutoTypingMap.java | 77 ------------------- .../jackhuang/hmcl/util/io/NetworkUtils.java | 1 - 19 files changed, 49 insertions(+), 164 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/AutoTypingMap.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 69706a64b5..b1d659e468 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -163,7 +163,7 @@ private void launch0() { setting.toLaunchOptions(profile.getGameDir()), launcherVisibility == LauncherVisibility.CLOSE ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. - : new HMCLProcessListener(authInfo, setting, gameVersion.isPresent()) + : new HMCLProcessListener(authInfo, gameVersion.isPresent()) )) .thenCompose(launcher -> { // launcher is prev task's result if (scriptFile == null) { @@ -436,7 +436,6 @@ public void execute() throws Exception { */ class HMCLProcessListener implements ProcessListener { - private final VersionSetting setting; private final Map forbiddenTokens; private ManagedProcess process; private boolean lwjgl; @@ -445,8 +444,7 @@ class HMCLProcessListener implements ProcessListener { private final LinkedList> logs; private final CountDownLatch latch = new CountDownLatch(1); - public HMCLProcessListener(AuthInfo authInfo, VersionSetting setting, boolean detectWindow) { - this.setting = setting; + public HMCLProcessListener(AuthInfo authInfo, boolean detectWindow) { this.detectWindow = detectWindow; if (authInfo == null) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java index 70f0cedad3..dfa7a5da95 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/MultiMCInstallVersionSettingTask.java @@ -20,12 +20,10 @@ import org.jackhuang.hmcl.mod.MultiMCInstanceConfiguration; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; -import org.jackhuang.hmcl.task.Scheduler; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import java.util.Objects; -import java.util.concurrent.Executor; public final class MultiMCInstallVersionSettingTask extends Task { private final Profile profile; 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 6b6d65a545..42e455e9fa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -33,7 +33,6 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.util.Duration; import org.jackhuang.hmcl.setting.Profile; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 8614697779..cf870c477d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -22,7 +22,6 @@ import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; -import javafx.beans.binding.Bindings; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.SkinBase; 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 bf718fce9b..1059ff178b 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 @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.construct; -import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.layout.HBox; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index a4aac7fdce..2a887de2e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -21,7 +21,6 @@ import com.jfoenix.svg.SVGGlyph; import javafx.beans.binding.Bindings; import javafx.collections.ListChangeListener; -import javafx.geometry.BoundingBox; import javafx.geometry.Bounds; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -56,7 +55,6 @@ public class DecoratorSkin extends SkinBase { private double xOffset, yOffset, newX, newY, initX, initY; private boolean allowMove, isDragging; - private BoundingBox originalBox, maximizedBox; /** * Constructor for all SkinBase instances. diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfilePage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfilePage.java index 27fba4c6b5..38fbe98d48 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfilePage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfilePage.java @@ -26,11 +26,9 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; -import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.FileItem; import org.jackhuang.hmcl.ui.construct.PageCloseEvent; @@ -38,7 +36,6 @@ import org.jackhuang.hmcl.util.StringUtils; import java.io.File; -import java.nio.file.Paths; import java.util.Optional; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index b7db33443a..0cbd6700c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.ListPage; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index 45c91f1c10..e7677176f6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -19,7 +19,6 @@ import javafx.stage.FileChooser; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; -import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.LauncherHelper; import org.jackhuang.hmcl.game.Version; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java index f3b6f7bd76..de6f150030 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java @@ -23,7 +23,6 @@ import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.animation.TransitionHandler; import org.jackhuang.hmcl.util.StringUtils; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index adf98e9e62..1b788a8aba 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -20,6 +20,7 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; import javafx.application.Platform; + import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.task.Task; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java index fcdc309472..3756038cc5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java @@ -17,8 +17,6 @@ */ package org.jackhuang.hmcl.download; -import org.jackhuang.hmcl.util.CacheRepository; - /** * * @author huangyuhui 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 0bc60b0bb8..d32e17dff6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download; import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList; -import org.jackhuang.hmcl.download.forge.ForgeVersionList; import org.jackhuang.hmcl.download.game.GameVersionList; import org.jackhuang.hmcl.download.liteloader.LiteLoaderVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java index 593842fdee..e71a406d0f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java @@ -36,7 +36,6 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.java deleted file mode 100644 index 33a96ba474..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import java.util.concurrent.Future; - -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; - -/** - * Determines how a task is executed. - * - * @author huangyuhui - */ -public abstract class Scheduler { - - /** - * Schedules the given task. - * - * @return the future - */ - public abstract Future schedule(ExceptionalRunnable block); - -} 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 e3393c7079..d439eac9fc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -17,10 +17,14 @@ */ package org.jackhuang.hmcl.task; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -108,15 +112,12 @@ private CompletableFuture executeTasks(Collection> tasks) { }) .thenApplyAsync(unused -> (Exception) null) .exceptionally(throwable -> { - if (!(throwable instanceof CompletionException)) - throw new AssertionError(); - Throwable resolved = resolveException(throwable); if (resolved instanceof Exception) { return (Exception) resolved; } else { // If an error occurred, we just rethrow it. - throw (CompletionException) throwable; + throw new CompletionException(throwable); } }); } @@ -137,9 +138,7 @@ private CompletableFuture executeTask(Task task) { return CompletableFuture.completedFuture(null); } }) - .thenComposeAsync(unused -> { - return executeTasks(task.getDependents()); - }) + .thenComposeAsync(unused -> executeTasks(task.getDependents())) .thenComposeAsync(dependentsException -> { boolean isDependentsSucceeded = dependentsException == null; @@ -160,9 +159,7 @@ private CompletableFuture executeTask(Task task) { rethrow(throwable); }); }) - .thenComposeAsync(unused -> { - return executeTasks(task.getDependencies()); - }) + .thenComposeAsync(unused -> executeTasks(task.getDependencies())) .thenComposeAsync(dependenciesException -> { boolean isDependenciesSucceeded = dependenciesException == null; @@ -176,7 +173,7 @@ private CompletableFuture executeTask(Task task) { return CompletableFuture.completedFuture(dependenciesException); } }) - .thenApplyAsync(dependenciesException -> { + .thenAcceptAsync(dependenciesException -> { boolean isDependenciesSucceeded = dependenciesException == null; if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) { @@ -193,14 +190,8 @@ private CompletableFuture executeTask(Task task) { taskListeners.forEach(it -> it.onFinished(task)); task.setState(Task.TaskState.SUCCEEDED); - - return null; }) - .thenApplyAsync(unused -> null) .exceptionally(throwable -> { - if (!(throwable instanceof CompletionException)) - throw new AssertionError(); - Throwable resolved = resolveException(throwable); if (resolved instanceof Exception) { Exception e = (Exception) resolved; @@ -226,7 +217,7 @@ private CompletableFuture executeTask(Task task) { task.setState(Task.TaskState.FAILED); } - throw (CompletionException) throwable; // rethrow error + throw new CompletionException(resolved); // rethrow error }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java index b1386aa05a..bffbbda6ba 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java @@ -25,29 +25,57 @@ */ public abstract class TaskListener implements EventListener { + /** + * Executed when a Task execution chain starts. + */ public void onStart() { } + /** + * Executed before the task's pre-execution and dependents execution. + * + * TaskState of this task is READY. + * + * @param task the task that gets ready. + */ public void onReady(Task task) { } + /** + * Executed when the task's execution starts. + * + * TaskState of this task is RUNNING. + * + * @param task the task which is being run. + */ public void onRunning(Task task) { } + /** + * Executed after the task's dependencies and post-execution finished. + * + * TaskState of the task is EXECUTED. + * + * @param task the task which finishes its work. + */ public void onFinished(Task task) { } + /** + * Executed when an exception occurred during the task's execution. + * + * @param task the task which finishes its work. + */ public void onFailed(Task task, Throwable throwable) { onFinished(task); } + /** + * Executed when the task execution chain stopped. + * + * @param success true if no error occurred during task execution. + * @param executor the task executor with responsibility to the task execution. + */ public void onStop(boolean success, TaskExecutor executor) { } - - public static class DefaultTaskListener extends TaskListener { - private DefaultTaskListener() { - } - - public static final DefaultTaskListener INSTANCE = new DefaultTaskListener(); - } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AutoTypingMap.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AutoTypingMap.java deleted file mode 100644 index 1bd342160d..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AutoTypingMap.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.util; - -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -/** - * A map that support auto casting. - * - * @author huangyuhui - */ -public final class AutoTypingMap { - - private final Map impl; - - public AutoTypingMap(Map impl) { - this.impl = impl; - } - - /** - * Get the value associated with given {@code key} in the mapping. - * - * Be careful of the return type {@code }, as you must ensure that {@code } is correct - * - * @param key the key that the value associated with - * @param the type of value which you must ensure type correction - * @return the value associated with given {@code key} - * @throws ClassCastException if the return type {@code } is incorrect. - */ - @SuppressWarnings("unchecked") - public synchronized V get(K key) throws ClassCastException { - return (V) impl.get(key); - } - - public synchronized Optional getOptional(K key) { - return Optional.ofNullable(get(key)); - } - - public synchronized void set(K key, Object value) { - if (value != null) - impl.put(key, value); - } - - public Collection values() { - return impl.values(); - } - - public Set keys() { - return impl.keySet(); - } - - public boolean containsKey(K key) { - return impl.containsKey(key); - } - - public Object remove(K key) { - return impl.remove(key); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java index f4e25c3fc4..05f9579f4d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java @@ -19,7 +19,6 @@ import java.io.*; import java.net.*; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; From 32d0d6a7ee876a7de7f0f1771f19b0a93a568cd2 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 26 Feb 2019 15:28:40 +0800 Subject: [PATCH 0058/2639] Add some task test --- .../java/org/jackhuang/hmcl/task/Task.java | 5 +++ .../org/jackhuang/hmcl/task/TaskExecutor.java | 8 ++--- .../org/jackhuang/hmcl/util/TaskTest.java | 36 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) 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 10e54b032e..65d592a871 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -76,6 +76,11 @@ final void setState(TaskState state) { // last exception private Exception exception; + /** + * When task has been cancelled, task.exception will be null. + * + * @return the exception thrown during execution, possibly from dependents or dependencies. + */ public final Exception getException() { return exception; } 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 d439eac9fc..08d5325f64 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -80,8 +80,10 @@ public boolean test() { return future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - } catch (ExecutionException | CancellationException e) { - e.printStackTrace(); + } catch (ExecutionException ignore) { + // We have dealt with ExecutionException in exception handling and uncaught exception handler. + } catch (CancellationException e) { + Logging.LOG.log(Level.INFO, "Task " + firstTask + " has been cancelled.", e); } return false; } @@ -202,8 +204,6 @@ private CompletableFuture executeTask(Task task) { } task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); - } else if (e instanceof CancellationException || e instanceof RejectedExecutionException) { - task.setException(e); } else { task.setException(e); exception = e; diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java index b432dc1f17..ac1b611f60 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java @@ -3,10 +3,14 @@ import javafx.embed.swing.JFXPanel; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; +import java.util.concurrent.CancellationException; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -68,4 +72,36 @@ public void testThenAccept() { Assert.assertTrue("Task does not succeed", result); Assert.assertTrue("ThenAccept has not been executed", flag.get()); } + + @Test + public void testCancellation() { + Task task = Task.runAsync(() -> Thread.sleep(200)); + TaskExecutor executor = task.executor(); + Lang.thread(() -> { + try { + Thread.sleep(100); + executor.cancel(); + } catch (InterruptedException e) { + Assume.assumeNoException(e); + } + }); + Assert.assertFalse("Task should fail because we have cancelled it", executor.test()); + Assert.assertNull("CancellationException should not be recorded.", executor.getException()); + Assert.assertNull("CancellationException should not be recorded.", task.getException()); + } + + @Test + public void testRejectedExecutionException() { + Schedulers.defaultScheduler(); + Schedulers.shutdown(); + + Task task = Task.runAsync(() -> { + Thread.sleep(1000); + }); + + boolean result = task.test(); + + Assert.assertFalse("Task should fail since ExecutorService is shut down and RejectedExecutionException should be thrown", result); + Assert.assertTrue("RejectedExecutionException should be recorded", task.getException() instanceof RejectedExecutionException); + } } \ No newline at end of file From 266c686a3a2f783efc529544d19f65d335a86ac5 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 4 Mar 2019 11:39:30 +0800 Subject: [PATCH 0059/2639] Fix forge 1.13 installation --- HMCL/build.gradle | 2 +- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- .../main/resources/assets/lang/I18N_zh.properties | 2 +- .../main/resources/assets/lang/I18N_zh_CN.properties | 2 +- .../hmcl/download/forge/ForgeInstallTask.java | 3 ++- .../hmcl/download/forge/ForgeNewInstallProfile.java | 12 +++++++++++- .../hmcl/download/forge/ForgeNewInstallTask.java | 8 ++++++++ .../hmcl/download/game/GameAssetDownloadTask.java | 1 + .../hmcl/download/game/LibraryDownloadTask.java | 4 ++-- .../org/jackhuang/hmcl/mod/CurseCompletionTask.java | 2 +- 10 files changed, 29 insertions(+), 9 deletions(-) diff --git a/HMCL/build.gradle b/HMCL/build.gradle index 07b47b5454..afa896d7cf 100644 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -112,7 +112,7 @@ def createExecutable(String suffix, String header) { processResources { ext.convertToBSS = { String resource -> - exclude resource + // exclude resource doFirst { def cssFile = new File(this.projectDir, "src/main/resources/" + resource) def bssFile = new File(this.projectDir, "build/compiled-resources/" + resource[0..-4] + "bss") diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 69c7b3d76e..be989d1c20 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -95,7 +95,7 @@ download.failed=Failed to download download.failed.empty=No candidates. Click here to return. download.failed.refresh=Unable to load version list. Click here to retry. download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) -download.provider.mojang=Mojang +download.provider.mojang=Mojang (Forge and OptiFine installation being downloaded from BMCLAPI) extension.bat=Windows Bat file extension.mod=Mod file diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index a60b08d16b..53364130ab 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -94,7 +94,7 @@ download.failed=下載失敗 download.failed.empty=沒有可供安裝的版本,點擊此處返回。 download.failed.refresh=載入版本列表失敗,點擊此處重試。 download.provider.bmclapi=BMCLAPI(bangbang93,https://bmclapi2.bangbang93.com/) -download.provider.mojang=官方伺服器(Mojang) +download.provider.mojang=官方伺服器(Forge 和 OptiFine 自動安裝的下載來源是 BMCLAPI) extension.bat=Windows 腳本 extension.mod=模組檔案 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 d743405e72..9d3c37abc5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -94,7 +94,7 @@ download.failed=下载失败 download.failed.empty=没有可供安装的版本,点击此处返回。 download.failed.refresh=加载版本列表失败,点击此处重试。 download.provider.bmclapi=BMCLAPI(bangbang93,https://bmclapi2.bangbang93.com/) -download.provider.mojang=官方(Mojang) +download.provider.mojang=官方(Forge 和 OptiFine 自动安装使用 BMCLAPI 下载源) extension.bat=Windows 脚本 extension.mod=模组文件 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 c29de94a50..d250c90843 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 @@ -58,7 +58,8 @@ public boolean doPreExecute() { public void preExecute() throws Exception { installer = Files.createTempFile("forge-installer", ".jar"); - dependent = new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), installer.toFile()); + dependent = new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), installer.toFile()) + .setCaching(true); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java index 3cd83c53a1..7ede714442 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java @@ -34,14 +34,16 @@ public class ForgeNewInstallProfile { private final int spec; private final String minecraft; private final String json; + private final Artifact path; private final List libraries; private final List processors; private final Map data; - public ForgeNewInstallProfile(int spec, String minecraft, String json, List libraries, List processors, Map data) { + public ForgeNewInstallProfile(int spec, String minecraft, String json, Artifact path, List libraries, List processors, Map data) { this.spec = spec; this.minecraft = minecraft; this.json = json; + this.path = path; this.libraries = libraries; this.processors = processors; this.data = data; @@ -69,6 +71,14 @@ public String getJson() { return json; } + /** + * Maven artifact path for the main jar to install. + * @return artifact path of the main jar. + */ + public Artifact getPath() { + return path; + } + /** * Libraries that processors depend on. * @return the required dependencies. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index fe1250485a..9773a32d2a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -107,6 +107,14 @@ public void preExecute() throws Exception { FileUtils.copyFile(file, dest); } } + + { + Path mainJar = profile.getPath().getPath(fs.getPath("maven")); + if (Files.exists(mainJar)) { + Path dest = gameRepository.getArtifactFile(version, profile.getPath()); + FileUtils.copyFile(mainJar, dest); + } + } } dependents.add(new GameLibrariesTask(dependencyManager, version, profile.getLibraries())); 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 9c435ce41e..1de7633818 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 @@ -89,6 +89,7 @@ public void execute() throws Exception { String url = dependencyManager.getDownloadProvider().getAssetBaseURL() + assetObject.getLocation(); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(url), file, new FileDownloadTask.IntegrityCheck("SHA-1", assetObject.getHash())); task.setName(assetObject.getHash()); + task.setCaching(true); dependencies.add(task .setCacheRepository(dependencyManager.getCacheRepository()) .setCaching(true) 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 311ffaa1a8..cdfa3d1dc8 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 @@ -128,12 +128,12 @@ public void preExecute() throws Exception { try { URL packXz = NetworkUtils.toURL(url + ".pack.xz"); if (NetworkUtils.urlExists(packXz)) { - task = new FileDownloadTask(packXz, xzFile, null); + task = new FileDownloadTask(packXz, xzFile, null).setCaching(true); xz = true; } else { task = new FileDownloadTask(NetworkUtils.toURL(url), jar, - library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null); + library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null).setCaching(true); xz = false; } } catch (IOException e) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java index 9bac795b1e..0a81865fd8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java @@ -140,7 +140,7 @@ public void execute() throws Exception { for (CurseManifestFile file : newManifest.getFiles()) if (StringUtils.isNotBlank(file.getFileName())) { if (!modManager.hasSimpleMod(file.getFileName())) { - dependencies.add(new FileDownloadTask(file.getUrl(), modManager.getSimpleModPath(file.getFileName()).toFile())); + dependencies.add(new FileDownloadTask(file.getUrl(), modManager.getSimpleModPath(file.getFileName()).toFile()).setCaching(true)); } } From 5b30617a6b5709a72442a26e1caa8ddcddfe5c1b Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 4 Mar 2019 12:27:09 +0800 Subject: [PATCH 0060/2639] Forbid user from installing both Forge 1.13 and OptiFine simultaneously --- .../jackhuang/hmcl/ui/download/InstallerWizardProvider.java | 3 +++ HMCL/src/main/resources/assets/lang/I18N.properties | 1 + HMCL/src/main/resources/assets/lang/I18N_zh.properties | 1 + HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 1 + .../org/jackhuang/hmcl/download/forge/ForgeInstallTask.java | 5 ----- .../jackhuang/hmcl/download/forge/ForgeNewInstallTask.java | 4 ++++ .../hmcl/download/optifine/OptiFineInstallTask.java | 5 +++++ 7 files changed, 15 insertions(+), 5 deletions(-) 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 6f826a1a95..f6edfcae9a 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 @@ -22,6 +22,7 @@ import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.game.LibraryDownloadException; +import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; @@ -125,6 +126,8 @@ public static void alertFailureMessage(Exception exception, Runnable next) { Controllers.dialog(i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); } else if (exception instanceof DownloadException) { Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); + } else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException) { + Controllers.dialog(i18n("install.failed.optifine_conflict"), i18n("install.failed"), MessageType.ERROR, next); } else { Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageType.ERROR, next); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index be989d1c20..730d73d0e7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -127,6 +127,7 @@ install=Install New Game install.failed=Failed to install install.failed.downloading=Failed to install due to some files not downloaded successfully install.failed.downloading.detail=Failed to download file: %s +install.failed.optifine_conflict=OptiFine and Forge are both installed simultaneously on Minecraft 1.13 install.installer.choose=Choose a %s version install.installer.forge=Forge install.installer.game=Game diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 53364130ab..896f75ca06 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -126,6 +126,7 @@ install=新增遊戲 install.failed=安裝失敗 install.failed.downloading=安裝失敗,部分文件未能完成下載 install.failed.downloading.detail=未能下載檔案:%s +install.failed.optifine_conflict=暫不支持 OptiFine 與 Forge 同時安裝於 Minecraft 1.13 install.installer.choose=選擇 %s 版本 install.installer.forge=Forge install.installer.game=遊戲 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 9d3c37abc5..2dcc349055 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -126,6 +126,7 @@ install=添加游戏 install.failed=安装失败 install.failed.downloading=安装失败,部分文件未能完成下载 install.failed.downloading.detail=未能下载文件:%s +install.failed.optifine_conflict=暂不支持 OptiFine 与 Forge 同时安装于 Minecraft 1.13 install.installer.choose=选择 %s 版本 install.installer.forge=Forge install.installer.game=游戏 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 d250c90843..7a3201f2f7 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 @@ -83,11 +83,6 @@ public Collection getDependencies() { return Collections.singleton(dependency); } - @Override - public boolean isRelyingOnDependencies() { - return false; - } - @Override public void execute() { if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index 9773a32d2a..d57da15d43 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -19,6 +19,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.game.GameLibrariesTask; +import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskResult; @@ -122,6 +123,9 @@ public void preExecute() throws Exception { @Override public void execute() throws Exception { + if ("net.minecraft.launchwrapper.Launch".equals(version.getMainClass())) + throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); + Path temp = Files.createTempDirectory("forge_installer"); int finished = 0; try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { 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 716ddfad45..8107d01790 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 @@ -66,6 +66,9 @@ public boolean isRelyingOnDependencies() { @Override public void execute() { + if ("cpw.mods.modlauncher.Launcher".equals(version.getMainClass())) + throw new UnsupportedOptiFineInstallationException(); + String remoteVersion = remote.getGameVersion() + "_" + remote.getSelfVersion(); Library library = new Library( @@ -90,4 +93,6 @@ public void execute() { dependencies.add(dependencyManager.checkLibraryCompletionAsync(version.setLibraries(libraries))); } + public static class UnsupportedOptiFineInstallationException extends UnsupportedOperationException { + } } From bf37db2cbe3606c41c797f3bd3ad4f4edf97549a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 5 Mar 2019 19:32:24 +0800 Subject: [PATCH 0061/2639] Fix #538 --- .../org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index b412c09ff6..85243055d7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -78,7 +78,7 @@ public void execute() { continue; String jar = null; for (ForgeVersion.File file : version.getFiles()) - if ("installer".equals(file.getCategory())) { + if ("installer".equals(file.getCategory()) && "jar".equals(file.getFormat())) { String classifier = gameVersion + "-" + version.getVersion() + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); String fileName = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat(); From 1eb4b1ca9e7bc08adec1ab7f7ce07cc4a7fa0899 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 5 Mar 2019 19:37:37 +0800 Subject: [PATCH 0062/2639] Fix unable to delete the version which failed to download --- .../java/org/jackhuang/hmcl/download/DefaultGameBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 60b8f01d6d..21e2ae11ba 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -72,7 +72,7 @@ public Task buildAsync() { return libraryTask; }).whenComplete((isDependentSucceeded, exception) -> { if (!isDependentSucceeded) - dependencyManager.getGameRepository().getVersionRoot(name).delete(); + dependencyManager.getGameRepository().removeVersionFromDisk(name); }); } From 78be1aaa7cade0714c32eaefe18800bbbaa84a0c Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 18 Mar 2019 13:43:17 +0800 Subject: [PATCH 0063/2639] Fix blank space in bottom of settings page --- .../org/jackhuang/hmcl/ui/SettingsView.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java index e56f6d46d2..27222ba7bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java @@ -19,6 +19,7 @@ import com.jfoenix.controls.*; import javafx.geometry.HPos; +import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.geometry.VPos; import javafx.scene.Cursor; @@ -72,7 +73,7 @@ public SettingsView() { { VBox rootPane = new VBox(); - rootPane.setStyle("-fx-padding: 18;"); + rootPane.setPadding(new Insets(36, 18, 36, 18)); { ComponentList settingsPane = new ComponentList(); { @@ -80,12 +81,31 @@ public SettingsView() { StackPane sponsorPane = new StackPane(); sponsorPane.setCursor(Cursor.HAND); sponsorPane.setOnMouseClicked(e -> onSponsor()); + + GridPane gridPane = new GridPane(); + + ColumnConstraints col = new ColumnConstraints(); + col.setHgrow(Priority.SOMETIMES); + col.setMaxWidth(Double.POSITIVE_INFINITY); + + gridPane.getColumnConstraints().setAll(col); + + RowConstraints row = new RowConstraints(); + row.setMinHeight(Double.NEGATIVE_INFINITY); + row.setValignment(VPos.TOP); + row.setVgrow(Priority.SOMETIMES); + gridPane.getRowConstraints().setAll(row); + { Label label = new Label(i18n("sponsor.hmcl")); label.setWrapText(true); - label.prefWidthProperty().bind(sponsorPane.widthProperty()); - sponsorPane.getChildren().add(label); + label.setTextAlignment(TextAlignment.JUSTIFY); + GridPane.setRowIndex(label, 0); + GridPane.setColumnIndex(label, 0); + gridPane.getChildren().add(label); } + + sponsorPane.getChildren().setAll(gridPane); settingsPane.getContent().add(sponsorPane); } From 32562d7435704d0129d117cdb82f1a8d21fe5fe3 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 18 Mar 2019 13:44:38 +0800 Subject: [PATCH 0064/2639] Revert JFoenix --- .../java/org/jackhuang/hmcl/Launcher.java | 10 ++++++---- .../org/jackhuang/hmcl/setting/Profile.java | 6 +++--- .../org/jackhuang/hmcl/setting/Profiles.java | 4 ++-- .../org/jackhuang/hmcl/ui/Controllers.java | 9 ++++++--- .../jackhuang/hmcl/ui/DialogController.java | 5 +++-- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 13 ++++++++++--- .../jackhuang/hmcl/ui/LeftPaneController.java | 4 ++-- .../hmcl/ui/account/AccountListItemSkin.java | 14 +++++--------- .../hmcl/ui/account/AddAccountPane.java | 10 ++++++---- .../hmcl/ui/construct/RipplerContainer.java | 6 +++--- .../ui/construct/TaskExecutorDialogPane.java | 5 +++-- .../jackhuang/hmcl/ui/versions/GameList.java | 6 +++--- .../hmcl/ui/versions/GameListItemSkin.java | 4 ++-- .../hmcl/ui/versions/ModListPage.java | 4 ++-- .../TaskExecutorDialogWizardDisplayer.java | 6 +++--- lib/JFoenix.jar | Bin 658061 -> 589462 bytes 16 files changed, 59 insertions(+), 47 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 87b0e7e99e..a609579f01 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl; -import com.jfoenix.utils.JFXUtilities; import javafx.application.Application; import javafx.application.Platform; import javafx.stage.Stage; @@ -25,7 +24,9 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.upgrade.UpdateChecker; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.CrashReporter; +import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.io.File; @@ -39,6 +40,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -97,7 +99,7 @@ public static void main(String[] args) { public static void stopApplication() { LOG.info("Stopping application.\n" + StringUtils.getStackTrace(Thread.currentThread().getStackTrace())); - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (Controllers.getStage() == null) return; Controllers.getStage().close(); @@ -111,7 +113,7 @@ public static void stopApplication() { public static void stopWithoutPlatform() { LOG.info("Stopping application without JavaFX Toolkit.\n" + StringUtils.getStackTrace(Thread.currentThread().getStackTrace())); - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (Controllers.getStage() == null) return; Controllers.getStage().close(); 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 29f87fea9a..b84a50e6da 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -19,7 +19,6 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.Observable; @@ -32,7 +31,7 @@ import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.ui.WeakListenerHolder; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.javafx.ObservableHelper; import java.io.File; @@ -40,6 +39,7 @@ import java.util.Optional; import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; /** * @@ -144,7 +144,7 @@ public Profile(String name, File initialGameDir, VersionSetting global, String s } private void checkSelectedVersion() { - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (!repository.isLoaded()) return; String newValue = selectedVersion.get(); if (!repository.hasVersion(newValue)) { 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 d925be84b5..58a2d14dec 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,6 @@ */ package org.jackhuang.hmcl.setting; -import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.Observable; import javafx.beans.property.*; @@ -36,6 +35,7 @@ import static javafx.collections.FXCollections.observableArrayList; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class Profiles { @@ -162,7 +162,7 @@ static void init() { }); EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> { - JFXUtilities.runInFX(() -> { + runInFX(() -> { Profile profile = selectedProfile.get(); if (profile != null && profile.getRepository() == event.getSource()) { selectedVersion.bind(profile.selectedVersionProperty()); 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 66e462d51f..970eb432f2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.utils.JFXUtilities; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.image.Image; @@ -34,8 +33,11 @@ import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.account.AccountList; import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage; -import org.jackhuang.hmcl.ui.construct.*; +import org.jackhuang.hmcl.ui.construct.InputDialogPane; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; +import org.jackhuang.hmcl.ui.construct.PopupMenu; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.ui.decorator.DecoratorController; import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider; import org.jackhuang.hmcl.ui.profile.ProfileList; @@ -58,6 +60,7 @@ import java.util.stream.Collectors; import static org.jackhuang.hmcl.setting.ConfigHolder.config; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class Controllers { @@ -174,7 +177,7 @@ public static MainPage getMainPage() { return node; }) .collect(Collectors.toList()); - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (profile == Profiles.getSelectedProfile()) mainPage.getVersions().setAll(children); }); 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 e2bcd98d25..48f559e549 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.utils.JFXUtilities; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthenticationException; @@ -29,13 +28,15 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; + public final class DialogController { public static AuthInfo logIn(Account account) throws CancellationException, AuthenticationException, InterruptedException { if (account instanceof YggdrasilAccount) { CountDownLatch latch = new CountDownLatch(1); AtomicReference res = new AtomicReference<>(null); - JFXUtilities.runInFX(() -> { + runInFX(() -> { AccountLoginPane pane = new AccountLoginPane(account, it -> { res.set(it); latch.countDown(); 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 f555d7f836..e47a3d9457 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.*; import javafx.animation.Animation; import javafx.animation.Interpolator; @@ -44,7 +43,7 @@ import javafx.util.Callback; import javafx.util.Duration; import javafx.util.StringConverter; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.javafx.ExtendedProperties; @@ -75,6 +74,14 @@ public final class FXUtils { private FXUtils() { } + public static void runInFX(Runnable runnable) { + if (Platform.isFxApplicationThread()) { + runnable.run(); + } else { + Platform.runLater(runnable); + } + } + public static void checkFxUserThread() { if (!Platform.isFxApplicationThread()) { throw new IllegalStateException("Not on FX application thread; currentThread = " @@ -252,7 +259,7 @@ public static void installSlowTooltip(Node node, String tooltip) { } public static void installTooltip(Node node, double openDelay, double visibleDelay, double closeDelay, Tooltip tooltip) { - JFXUtilities.runInFX(() -> { + runInFX(() -> { try { // Java 8 Class behaviorClass = Class.forName("javafx.scene.control.Tooltip$TooltipBehavior"); 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 ad0160dee6..ecaad61bf7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.scene.image.Image; import javafx.scene.layout.Region; @@ -43,6 +42,7 @@ import java.io.File; import java.util.concurrent.atomic.AtomicReference; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class LeftPaneController extends AdvancedListBox { @@ -111,7 +111,7 @@ private void addNewAccount() { private boolean checkedModpack = false; private void onRefreshedVersions(HMCLGameRepository repository) { - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (!checkedModpack) { checkedModpack = true; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 8614697779..1b0801687b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -17,12 +17,9 @@ */ package org.jackhuang.hmcl.ui.account; -import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; - -import javafx.beans.binding.Bindings; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.SkinBase; @@ -31,17 +28,16 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; - +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.util.javafx.BindingMapping; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; - public class AccountListItemSkin extends SkinBase { public AccountListItemSkin(AccountListItem skinnable) { @@ -92,7 +88,7 @@ public void fire() { btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); btnRefresh.getStyleClass().add("toggle-icon4"); btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh"))); + runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh"))); right.getChildren().add(btnRefresh); JFXButton btnRemove = new JFXButton(); @@ -100,7 +96,7 @@ public void fire() { btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRemove, i18n("button.delete"))); + runInFX(() -> FXUtils.installFastTooltip(btnRemove, i18n("button.delete"))); right.getChildren().add(btnRemove); root.setRight(right); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 579548f804..db4968d88f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -17,9 +17,10 @@ */ package org.jackhuang.hmcl.ui.account; -import com.jfoenix.utils.JFXUtilities; -import com.jfoenix.controls.*; - +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXComboBox; +import com.jfoenix.controls.JFXPasswordField; +import com.jfoenix.controls.JFXTextField; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.property.ListProperty; @@ -53,6 +54,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; + import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; import static java.util.Objects.requireNonNull; @@ -293,7 +295,7 @@ public GameProfile select(YggdrasilService service, List profiles) } catch (InterruptedException ignore) { throw new NoSelectedCharacterException(); } finally { - JFXUtilities.runInFX(() -> Selector.this.fireEvent(new DialogCloseEvent())); + runInFX(() -> Selector.this.fireEvent(new DialogCloseEvent())); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java index b1e274037f..f4d7c25e79 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java @@ -75,12 +75,12 @@ public RipplerContainer(@NamedArg("container") Node container) { focusedProperty().addListener((a, b, newValue) -> { if (newValue) { if (!isPressed()) - buttonRippler.setOverlayVisible(true); + buttonRippler.showOverlay(); } else { - buttonRippler.setOverlayVisible(false); + buttonRippler.hideOverlay(); } }); - pressedProperty().addListener(o -> buttonRippler.setOverlayVisible(false)); + pressedProperty().addListener(o -> buttonRippler.hideOverlay()); setPickOnBounds(false); buttonContainer.setPickOnBounds(false); 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 53ebbc398e..d002196a5f 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 @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.construct; -import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXProgressBar; import javafx.application.Platform; @@ -34,6 +33,8 @@ import java.util.Optional; import java.util.function.Consumer; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; + public class TaskExecutorDialogPane extends StackPane { private TaskExecutor executor; private Consumer onCancel; @@ -121,6 +122,6 @@ public void setProgress(double progress) { public void setCancel(Consumer onCancel) { this.onCancel = onCancel; - JFXUtilities.runInFX(() -> btnCancel.setDisable(onCancel == null)); + runInFX(() -> btnCancel.setDisable(onCancel == null)); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java index 85728e67ef..a30eff08dc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.utils.JFXUtilities; import javafx.application.Platform; import javafx.beans.property.*; import javafx.collections.FXCollections; @@ -43,6 +42,7 @@ import java.util.List; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class GameList extends Control implements DecoratorPage { @@ -55,7 +55,7 @@ public class GameList extends Control implements DecoratorPage { public GameList() { EventBus.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(event -> { if (event.getSource() == Profiles.getSelectedProfile().getRepository()) - JFXUtilities.runInFX(() -> loading.set(true)); + runInFX(() -> loading.set(true)); }); Profiles.registerVersionsListener(this::loadVersions); @@ -72,7 +72,7 @@ private void loadVersions(Profile profile) { .thenComparing(a -> VersionNumber.asVersion(a.getId()))) .map(version -> new GameListItem(toggleGroup, profile, version.getId())) .collect(Collectors.toList()); - JFXUtilities.runInFX(() -> { + runInFX(() -> { if (profile == Profiles.getSelectedProfile()) { loading.set(false); items.setAll(children); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index b105c02706..9720c77fd7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXPopup; import com.jfoenix.controls.JFXRadioButton; @@ -33,6 +32,7 @@ import org.jackhuang.hmcl.ui.construct.MenuSeparator; import org.jackhuang.hmcl.ui.construct.PopupMenu; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class GameListItemSkin extends SkinBase { @@ -73,7 +73,7 @@ public GameListItemSkin(GameListItem skinnable) { btnUpgrade.setOnMouseClicked(e -> skinnable.update()); btnUpgrade.getStyleClass().add("toggle-icon4"); btnUpgrade.setGraphic(SVG.update(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnUpgrade, i18n("version.update"))); + runInFX(() -> FXUtils.installFastTooltip(btnUpgrade, i18n("version.update"))); right.getChildren().add(btnUpgrade); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 62a4da7211..6d6d2791ed 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.versions; -import com.jfoenix.utils.JFXUtilities; import com.jfoenix.controls.JFXTabPane; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ListProperty; @@ -47,6 +46,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class ModListPage extends Control { @@ -87,7 +87,7 @@ public void loadMods(ModManager modManager) { this.modManager = modManager; Task.ofResult(() -> { synchronized (ModListPage.this) { - JFXUtilities.runInFX(() -> loadingProperty().set(true)); + runInFX(() -> loadingProperty().set(true)); modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 48fb46f0a4..db46ed19ef 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.wizard; -import com.jfoenix.utils.JFXUtilities; import javafx.beans.property.StringProperty; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; @@ -30,6 +29,7 @@ import java.util.Map; +import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer { @@ -59,11 +59,11 @@ else if (subtitle instanceof String) pane.setSubtitle((String) subtitle); } - JFXUtilities.runInFX(() -> { + runInFX(() -> { TaskExecutor executor = task.executor(new TaskListener() { @Override public void onStop(boolean success, TaskExecutor executor) { - JFXUtilities.runInFX(() -> { + runInFX(() -> { pane.fireEvent(new DialogCloseEvent()); if (success) { if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) diff --git a/lib/JFoenix.jar b/lib/JFoenix.jar index 4712ea8cdd6b45d643a9ec23e290d52f06cad43f..1672f1ebed5a34b230400c8d57875d659f877aca 100644 GIT binary patch delta 348872 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%0A2ElPjj(%^j?*ODO(!H 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�$ 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%0DEjG9WfH6!+W3f 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	&1
zH&*WD@HqQjYwOJ*yQzn{6|3u>#B5V?O&?)SO-J*Duua<*scBWq`bX_0HIUFjzW24w
z4PbU*3r+|J+*w4#2X;{#*iLMqvi^ot_X<<{T8C>MI4cMK7(QB4sy2b22X%x
zA}su4qp;C&fL$()&K&FTvZa0a+Aewg6tHYTN7&RBYzxkf17l~9u)Ah$)RA$CDNGM}
zocfZ+(RQ_pkPz3Zr;XwkUS+e+$ZZ=6cu9(Z>RV!Ttg?gQz>l5y17GEdpo`u<@4u#}
z4TlL=h8I0a5QoubxdbPFK!ye9Y_EdYf3f4pEcWUg(o=(C_6CZ$M$#~~%hzy<1W4lF
z&l?jgCFQ~#eU{KeJUH9g-`;yBI8Cnk#I3`qL!7)3`8w)^cWK6*Z{uRFX>gz8h%Hw0@YWI@E|95LFJ_>oC2
zb8aw%0Hv6`Q{oSk(3%OR{U0XLHN8QGQt!6!YljSGev~8_WX#gEAe9tysIrB@?$^<0
z%~TJt1Uu?dH-7Qg!)U;sWG_X6@oOq%lq4D92Oebm3Drf=LRD#TW3SPiY1dpmPlW$I
z*&F%RH2wirBzx0;fP7W*J-#T@^nU{@Kew;}w(2!r7Gxd%!4|mM
zK_#lRldx9W<+9tIzeubNmK!_0?v+24UWp&@1P&nY?>YXsn7Ml@A2_`9X0$i5PV+kd
z-iQKxdVe7N61Vt{G$@6|al;%XPeP`q$!nZoUXM{W5(D+^MidVO*YW9^oH6fi8I!mR
z0Jod+t2xxN$vwJ*hDnoKAvR@5a;mbTBh%Pik4R_f!F7
zNO+OO=A`UGYumvkIKIb*r_6wwKe1sN0CEUNIYb@}>HWZJ#l{7LfJZ?$TQdSD1p
zWsU{Z$tw!zjdPccpsQo_=FG^7rB@WYiVj;EFWJjG-N#59NqDI1)f0oulY
zNrP0~QhgLf=>>a}C}_|M;IgQv7)}N5k2j5NY)NcA2wqCi(cBaM_t^~JU>}E6~wKAwq>_fkc
zn>?x>5qeF}^GN11?0`K1Ll?~z4^X)>Vnps5dIWK2#M3c~>kUWRb?YB@;0~Y=2hc
zeP%Q^7ItE;LhLkcI1FeT|K%`(r%F<5`$~ITDEI>GD)F7b(~t6!5?}TcJYlLUgt7Yx
z<3nKdaQKyM9}Gw)$;Y3`3{XBnS31JFU%Csr0g5+HKaPQUzxyG$;KE_mfa@AosH25A
z!XYx!NBk#j9-=OhU&Q}|LW(SKolKY~W6)U#bP7ptB3GH!#&rI;?Mfqq^^0wBH-II9
zvP9Z&6!8k8nihfGO>$pHH!E_Te3bku*@@om*Eh09d=x${8!4YS2+-yd=X4I9%#oDC
zq_r~#?qy6aGLRp1mx%DqYX5#=I`Mvl+;zL5XOe5}b$K3!t8tDM;KMyhq~r
zk!H(x?^4Zdn?K>519F=enb%*O&VLeuTK`oWNhmEl~DrzqL9hU%J&JPWrMF-2`Qop
z)Z)M&?t~8D4#7f0&Rc+t`D&|aC~3_x4CR$z%JM#ez9|kZqX+dyd9Spx+HZBO#!a`n
z108d^C^**#>0**E;9oE&7k-Dsj>Y--&I?5l;W6;at$I^_>8o77@K$@=D!DEhnpkjF
zrJ*-n766d37ezu=zDrX04w_Jj$2c-4bKK(1mxQ?f}#o2=fiAB~{Ws
zFanPK-Br?+#L18HyzvCEuYU(rVo`@s)hd*yoyjVVXv<$sX$(&VPW@Bqe!#uldk!zODjuY0*)
zc4YfX_{smnCjVR^^4E0=_BNKro@C7bV)QBNepR>7_~sdOwJ<7X0t0)>4SbI3cj13%C{Ln4GpA^W
zh#llyvzbU{)DSonEb0EfwueXx3Kj`NB}l|3juJj??|BL{8D2K#@tFgMG8(LoG4Hqd
z^%%jW3;5p0Jm;TUyO89e_n8~2ycQlRe<*sam}P$Bt@e;6*QsyXD$?-SZEmeQh5!=9
z-F6%g#|1maTGQAKL>EF}Hs(-(i!n+Pdr?Fhn0lrR=#+Uxv^8n!*UIgof75SQDwcL%
zaCfy#@m1_oS%RsavT86Uqii|Fy!PZfToc|qM47k!*vxdPF((dfrZC{b#A1ow
zvZ4Gg8Zy9RG{n+W3%;>RSwpf_N(p%T^#=?ewSO$5n!VQTQeE4-4_a#3o=DDt-qdW;
z)+1IU0f)r9z))&AseC$F+1aiz%s9X^jxvB<
z^l={5^)Vg{KSrc2vyY9hPmO7#5Fi{S@$ijr32ZHaOgdAULVgQnFxsZY14NBi)aVXu
zl#z))WHG1dOdJ-?AU~Ypwz|=4Lx@9@Tk-yTBmWE?pKsd}_Rs)xCV$~8TE%1pYI+J2
zhiCK=yw;qT4-4LQ1cg@F3fc&$AQ$z^|8G)08F3YqbO|8(-G{CtL3lZQyw2m#YIB@0)DZ>`K+Ga&!D_&iswy6e=jXIxHaROL#ZCn+F*Rnh89zyA
z6^Tp+A@x|bXB(;!jtIIDVg}
z>Cc8`RY3>@2JCIt6T()MZ0A3ya)i4DC4Wk?dL%@nqAL3JRCr}ll1BXi;4dS#Up+rw
z2B1m0zK~&lqWw^O_L+|+A^wrFS^p&BVDo&>t*#YJq1NF}nbdQN#uP@^e-+(avGf}l
z+pRRxArQ?Mix2W$FB5^CWSaC~e$wXP1pOjJ5QeKk6SLYd*Jd}%pO+X(Z(#1b&(+ft
zZI?^mn7b26lLfZuvc0JrAR?=RoP~|6?lFe?=rUPh~W9q)&Jrrn=}r6a|Fe)?6+!T_|Y=4no8iePblF0IVdqerIA
zNygLh4z(Lu>2cWisq`y!Rxd8<0%~&%o6R3>#q78>>{xa7+w;64E5cbW7@|%&M|J0C
zw3hRCMfag6^1}W3mRTS1!5W3`YJu4#3BjpNmQkZpmO^c;FM*<8>JOH~Gc}rrjO(pBGb(7v&@ujJI?B^P#^-lM2?VD*USP3ORIMMaT
z&srp$@Ob#N8IL1l^_O(J(Xcl2^GNH(_voTR7
z7~E~XyO+G7?e?hupkOD(mij(|H6vp&GItsHt+|d2PT={L1>P=)?opQaSVc!fhnZ_^
z$@Nk0hW#vGalH<2x(OD07c)l`oid&Xh-6)35E)NZF_?Py7vP(#T3zuT0v$RzQXyn(
zRWl5vDL7$;!*0d3Cs#mZr0GV=%w5A+;~pP6?UP0?B@O?eISv1?FSISPsNxNH&jGG}
z#S_l9#7c7o5=@Wk4bXPQSBp5)pQ7My?Skq(dJDK{v2>fe{BjURwY1z7X+}wlZ+Pp=
zvg=t$E>`k3c7XV;XUu)tq@Euoc;k+vzb5XlO&EB1`M9|nPaUi0i|rJ7ca^I&vIzak
z(+=5B=2HW&=Ye6;aw5AW7=O~vzTQg-aV~&eMPiIS?S7X&nN7&)YCpjY8vQ1Wn2TlH
zM~4QT`7-dt$zy$QbxB?jzvA}GMnKI=-}JUC{8vY*bSOXwS^(V-_h5k6nfu!bWCL?w
z)a{6=xHxrd_o)T^Z7F{<#@30PP03hnCUnt4qoL~s*LA3|<^po5vG)RAu0tAE(c1Ny
zOf{}jg?VPcphml}-gdM_ZMfU|L}B|+Td;fhBD}Enc5W1oqRzHnbaL|yBtC-0BSpVf
z87qRaQ)z%7)O}9DCwHz+6JZe{t}AD(*P7)Fa#>nA@jy6;)~g!vpPB+YJM{W(qE8fy
z$Jw!;sQ%C+Bl&q$>uc2a8+5R9_
z6Z4BV9MLRBh>t!w1i%inmzCkT&`KxhJ~wff;1kYCD3mZa)|$srQ`wOUc}TDQJ0Otl~9_UPUMHe
zcmooU$|fTcEw&F&ec6l!NN=p=|Z&)i*DMFVh)hPTp7+w89UhVr?$$6Bt4tMXYJT#c72-5Fy
z6=wG=9ja2R7KL{OE#M%sd0Ke5GKU}q7oqbc%^W_-1W;%xDQEkA-dC038bv*Pv|ejmYhyKHC?!Jp0ywm@#Cid>)$VtY
z$U2uIt=}#ys6j6RFR`GzpM#e+pivRyu<=(wgn&l$?eE9;0D}%OL^IY;aO^|P!LpQ5
z!sut)mEnsF)^CA#`xBUpfnrN_K&~y(+&e1W8t+K~(+`*PP6pk?j81OlEJek@6V*O4
zB|^$0>qvkuH}4%zA9YFjU$%AlDkyyk(=z`LwhT^E!7CP_k)iYdTnNZkw!|5J`N9cE
zn!OenF5vG$l42S%hDN3~Vm9`ME+Y1JE>89~|9asn{cA;597q)Y6tJfn1^KWiyAOs>MDh7hv*E$*B`py?7_U?FcPhS^+(fn<
z5MZK%t_@lBkTLv1mJ@%HwiE2i*OW&5^LskP+c%C~#(4GT_3ppzEiwh@wRdjpT{&{@
z*2<-ib8W4dbHi~8o$D8OUbtksH@n6J(-Y%`G~67i-ii4#Lx$i
z(hXZ(0HC&CilISpVZnD9@Es05hnGs?v>yeD=Cyl~GlX!zrQa)$?Z<)v`L}IOIz`JQ
z70B@Sa0+rEPUnJRUoJZilJ;v1_`jZrnxT!QiJ^<3k&WrUJ(d(D*}odmd}r4f
zYihQ4bS)5Z5Vz2TLIM@an-sp^#BY|GN^c~S>8=$4#)AZY5t2_`EiDB?a-k06f2>#6f6<_9ly4(#{Y+2B-J{
zcb8lw?n+eC@M7_OX}DlbNm`PTFsD1oN6y^dbPe(--LDs9Hg_l7Zz2W_NNpNm!Ei7q
z?vj(f(*#{wXQ~!lVycciG-MxJmq=ucq_*r+?LjJ{>q80CD;6LENe^D!9Unj!9E7-cD}dwkSwCtd~>NhvJ{j
z#>paiZ~u2QD9C-eKY{tDa+oRrNsIW^4#7wY
z1SItpjVO|kPQV+j&v+33Mb3LZ`llC-ZWNpK01^m@6fLc85d=3C3>cwt_!SB2?_sU$
zpum#uz-dCxnT>HMTEgGCma4+IkNl}J^^Be)}~_i#;(p%Vj3!@
z9xh^*rZy)32O3ebwf?Ht`+ehb9`$TC_dSiWukV)99u&FGB1w)9ve4rvs}UARo-|vx
z@!Cx3?#u)nn4^FH{_=%c?QKv$l^7VBo12;EX6&v$KcByH`5${6>|)q)DD*o8Rj2gn
zy4D{7_F|*F;o|ytAyXnO<9;HVzeN*H_Nz$H_v;dyWL7$oxHnEzI_64-jtPYod?=Ag
zRb8NqxLSMX^;%{?gJX6|jr;j=r@9S557#ZQ2U5OnRQ7$owlPh#aTfTM$QLnrh$Lwf
z8>kx|jvQ7*((JizrX@pYtWs5bEk~U|G_nk~+lEpCC;PV?_^Jq!0OL=6D
zB@;iXdokroCNN*<^bm>MAucLPy1EcAHnZj)i2j(YxeU7cywyjFxXEwk;Jt`m;|u)*
z7$?#(rj)uXejApXDJFNcwA83mQqa^W=F=g+Oj;ICp)>e{yYh_q8D1FnJYRbwgD1)o
zm4AoB`D5C`vnOb|d`j0>^m7=K%}mzkdKMCpd?TkVQd_dmjYC``^*0EvOQ3(
z@zRi@PP1WuGjnjECVXpuZ+HyA8jHPCk7sqrCfc~KuQ=o!!;Xpb&X8(B=hwc*09=hS
zOR`sH!63et;mEY8YVS-tmB>wbk0SCJ^$#$UQ@v;(f@%lyNq4h}bB;t#F^qSMer<33
z2n9P&KQt?J@Ot&5^FqAmKOO~dZxt(ZrqqE}5olC5Eeu9E7tDCtOB?zCz=$<=1uAU!
zxfJsTrWjV$j7RT`c&(N9(4#1xblBWs+E-Q5(xn%GK9`YVENLtmMsHw~3Kf
z!l$+n)A%p=RU{r*-pw|Eac>fjKaN;7WhT>TKN2=ibW*E`mt94<_22Uz7kVmfODj##
zywC|??bQ$Id{as%q0@>wZbdaSNpdW;HWX2}gdn-`HwNfoTk*5m2;FCncNnBFO7S-O
zn}QlSk9YV9G}0X%ph4jV`#F&NOG-mwa2zw-FT?>TC=p1ka#*`O
zgS!cgb#4gZj41Q$+7a*_2|Q_(w40C(Sm>ylrE8IS
zvrB@nQvova9|@T)(eF-y)H7{~)ew$!qrmT4vM04I{{iwW{D$Ud|BCL~2x)#ez_frA
zb!%^2adf|BrLH+I--w(6DUrEiNgU1g@{*<x*D}KQ)?E8_`Dw`CNdtgxsE3?RsnCv
z{c%7(5P+zCB7y}6o+-(zF0oq$Jbl1W2nKKTkCD;>Lk=_YQL7Ol2|KxdxLX_;ro#=-
zQQhQh^3lL-GifJ96lD}~5#%_DJ*hp(z1IBTK@6R~M6z+39vt(><-I3vf|z|=51A<+
z-cU+5-iR_b-WYQg-l{z=aD36-DXyzP%VXA|2IX6Hs$(>^SMYfrhp<3xR!x98F`vLO
z)Vhw8IsUpk{3@f8lUA_>2}#p%K=3L-#knqsGJ;?#dLZL7Crq0jQd!6
z^U8dNV?!vrZCj~LSPs4B_|12~=p(+ikhE
z)cc^?=|jpm$6A`>%z*sUb&jI}Q#{%TsA|u%!yEoq2E3vj$;!fYkd%D)d6Dyb;+&za
z+6*35y4n=_eP3#|33@qfsI2P&H^}>GqP^B>^yz5+cb_r|MUJLT6lZ`B`!u)90f;a8
zJF$&GQ$D+mTAG&w{?;gj-)|mdlNk=xEpaV)@ocb!IW?uMnOXs?sICrsU?D{|Szhw#U_2k4I~59MKP5A9*Z
zYY}{bzBp_Ke1Tpb?yFvN*Eba>-^ACz;CF1l+I>t9^+870H>ucnt;B7KTkS59;gc^N
zVfo)DZGn$2I)gBGR{bchZ@|B++DeO}&uRGMf8%oV4-leXNSOopex!EXIZKPj82q_V
zyP?Df42jcx6z>0M%fod|@+teC^PoV+XMvNNM95*o-Bu+;zzTZa7@*y}#C!p}e2p*W
z@JM;4K9f_uO`enpL0%BEsw@fK4&LsLxRgkIu8}(O@`d7@)@zoo6mCcvCUWR0z(?X5
z5V3yaBCG19DEtmsZ>^BBqa{sC8ttH{7&bem_ALw(Rc^&QHmcB|SAQhqSX|>gUGLA~
zyW*~%`e+Eu%@j8a5$ccJRp{7uqFDa#C%m&}>96udPufC5F*FcG2B9|^%5Kv^6AkTt^DINHYXl*v3
zBl`#6wMC^BXt5l;9~WIZMURb4VUPPeOvU#=4p6O-=!M=+L+7`L1mP#vg*MceP6c
z0*K)GMIr>K7mCk#L&#K|QdhRI;s-elu1`403$AQ{5|U*k$rNPW-c(!*yFQsn9qhA_
z1QsKoJyQ#D64NG~!!D@UgezzTbEIKVi+<0GK9QB_^BrcLU%Fk$rCc3p4X?8SJPwqu
zW7-F0&qO=LrZ86&KkjsKqsHc`n(m>e;%+x{ya=VRUruI!lDaiTFVR+rEYG@;Bc%DR*~&anov+>nCKV5M@iLtQ?5S6!oJs77yiy7_yj*jT$wMs@fTV+U5u(d~
zwT521+n;b@2Wvz)dI40^ZdvFzh62VbEXY*>+^l4}{bcK2MaApmE3@l5h8^C<=oGV6
zs_8l1UMvNNsP#Vf+9a74QjgukUOFQhCY
zj=pOb7TJP(t2vy*JfznD-i-UiKCree@nu8sK+}FA&fjHjAsBWOvqt<0j<8Ezx;^g#
zxMS6sY8=_&n%MV@?fR8FUd#xgM_m~54h_eo+Ib)>Vs9~kJ%F@1Gi48-!6!SQ2M2;#
z5(=J8u`I*K<&&Tjy*9NE#}zXT7Aom#MKI)huvY%5=M$kLzVnRV+fu%qQow*6v}y5z
zrEHg)e*isxbPn)MA5l(8nl$4BH~ze?L4
zB#GEWA8NI@df3YpUTq$t+DbmSbbLuu26BXz4%Hpp`oI#OOyJ```aYZt7ZLYRfPiEf
z|AO|Y0XbTp1}ck-0_F`}69);VM9|tqg1_htfWXs;*vWuNRww+4?Koxh5(7qMvNP&d
ztQI?3?NqB)Ds7vu)MQPOsyjnE7OWPR*3`7qI$Bk=nqU}S+?_4e+J|9vLpUNlJnC-4AGXCk#D+%M+*{6GSQ*QNrTyky=
zmxW5XCwr0&9TG1_OoQYgvTnC%xo3NpyqlvXydwM)$)yvr6OE>l1zC8!>QqzC%Avrj
zfHvxR|H_SIQ^C8OE`LNf$9{E60^
z2PjtK&$zd{76BCF%iNehcDw>`OllP~Q(%6K?JhECO@66;W34ubWtv%P6O6|H>{G1#KA3(Ipn}Ck6v?Py5D+H0^DzI7}zLBHX=wqCEL+lfV`Ry3c@Tv~qgV+9&P0VdqlJ
zaOf(;Blt>Z&WGG%gZOGc&;31q4V`b@yKRW7yq5baw|nsZb99y$LuvD7FT-w(SQ`W37jPe?&3Z$O5?NgRXu
zSa~^bEOjIQLd@!$S)1Uw!KWB~*HS05KeoH`$T2+LG5o8kjhva->l?Bo8V~NC#I6F7
z(JbWb-oWNMWGHiTT#xJO8bZ!#BFs2uQC$qD;SV)hIP+6fnWQ;-|E4{Gd>o6#!_4%P
zIhF{~T01(ZKat9;lTtcH4FHvS1A642%R%{rJo(ZE;tTCCd1cqnGNOhxgm&}Q;^TFU
zB9fvJaBeR_n*}w^F#157UY(uFOI1Oj;drQV>^e1J2+Fn07s*e?O3{jG;5FtnXguyO
zMZT%e=sif88=NPIF6UQUJ8^IxMLj(){9wGwK_$l85@gjCHF(Y;Pk`WM!nz8_2LcVMKEb6zPJ49H+tft*j-mGZ&lFM;=sEgYPC>lFf=p1gaF9xZPfGHaPf(t5Srh^Z#09R&L(A&P)Z!*N$zOBs0AJ8oz9A$5XM
zj|H)^r4sML^Fh+pNQeI_-$*vH!#CFhSA`Nu(sEmRfxwDtlG&j5Uf}Es>!wS`F0QOe
zWDP7=N0QtAj3c$^)XqJ$1~$<5i~2OmIZisqwq(o0a&I-$q)Kn2gfsHa6r-;)wpih5`DSpV#eGX9gbUdmZiM2^bG$~VMuqqw#41priRWrTc
zdL&AI&poDB&I8KO;(h{%^2rayi66_QFz3l-REsX9Wh7_-X}Kz=N*yv^TN#zmf(f0L
zH$&Y46)se}?Hn32PWrpDlv<6g;eY
z##v}bBEb=Y=b9-LeHGqJc(d73{Iz^!euD^m;+p~(SO!%1@NENW$7*FJGom~Is`H*h
z98)J)#Ya-g+U^@G~jMMtu1iYVLZnq9Yn*7|=+n~Ty*KJdz7D}f3jcUK$+W6_ETI+mC*73o{YT;hNbvi@F~VB`l@Cf?RYCRM
zjZdX#(hrSYd6f^2&#&iaQP!7N`GyUsy#+j@r2O1rMBn;xs}5H4A>Vak4Tm?-wBtYZ
z%?2Rm&y}95hL13EG~!@F6HB+4aH*i;MX-X;Me=An2Pf&AR_%2AO0!8FKb}ypDT^rypcKK@NyvO7bHrHSXsNZm
zSW#GBTTp6ksi;wnELbRM!Io!(Ypq-yuLnR=4fD=k0?YoK9+R{{7w=IZ%0Crvc&CdO
z#>IABN{>>IDdZ*$ut&>qMp3enM?7*>W+S3_sirMk$6QiKZ6(tYqoJKsX_QT|l-8kk
zTYK-BwCzPN=rwRB<1(ZmWK)ooUgwtI4}Cc*ePNF&&!H%z9yugYJ9j$Zy1i7VTL*xo
z4;@nN%qv{ppPGjzi=Ns6A4QO43+p~mmzJC|ofnG>k*VeAG7k+ZVW5}I7ha(%WNd1V
z4>PFV-%9I9VnCgd8K2z6J394U0LA87$of(t1=h7&^PFk%UAp2sm}^_6H#96^ggb7C
zAxDGq8~hNs%vvv5#HN>wG3EoaK?f+@QhJ)ipZB!ed39(v*DL(!F|Ej*C3c)sx_g0n
z%%8^(kr^LiTcm2iz_Tl#5_r=qc0FI7bu_{|te0exPc}~O_Ue_4mi{j4C_75U4}8mIGHlRKLiZw!3jgo3EF;Q}sMpl%((P|4UIpL#j4oahd
zjPy%kOlI!rCETJv5LyHFE=b}c4@?F;5c7CLheIsu%$&C*WE9hDEe~#7l1I_7<}Ge#
z`5gW+wR-Ec@`?@OnaA1*U%QU1A=Ipng@n4S^6B;wUJ`5IIb}K$HGu=v&syC^nONs?
zq#y1moqULYqGqlI{S|8#$(uxualJShr-{g>5=Ui;$e}oh8Vcs5?2P`6qN*7XO(R
z%%xq;ZpMQSppQ8Lv^r3(;M}D{V{V6yI_y^$6Zluk2^Vy}G4dzia~FgKU!U#56@OA5+n4
z@K2O7XOm`?MCZh_&8Y4%sZ-Nc7ahv09<;;5O&Kf;;k>+%cG^>#
zCV^iTt?Grb^yMW`l)d{Gd32*NQWe5GasM0^_DG%QqU(>!}Ryi2?F|-kp){vh{^BkfwMGDP8f$baG7K5Y;o!{1zoXc6){>BIdX*vXT*rM
zrOiz#+`HoH{iL-4kQe^CwIzi8N*uF)Tp%|EA7|tNr$QYm53{!SyqmE*KZCXkJ5QC@
zMq&8I$eZF23n`zeyyRK|DTa#kA0WDjbZ}mbpugpJ=*{OuetD9<4c{X8c6$uVKA|H6
z;88MQ-en51&^ttdJsl_4>CC&(NgX>)XC!o4s~f@8G?9zEEZ~l;nZ#nS@NJ^iKy)np
ztAH2)5LoK#a7r^hK$w0B+4m?ZGruhvP&S0?bfkZr7@_0d%hWd*)SVZ=wQxPLWI=Ha
zyjG|MRN~#j7(2aVeaE1q@7IA$JqgzjFx0vPK!uK*cnc)rn?zWIhV;
zEd1%;t`6KS1}?FxoX|-dKae(;r2<*H?Y{~eBfe>qT}*3b6lLIG|gIEXxHD@=(W=nAoSS->WvkcnIwEi)PaHr+gN&7iVY
zL0vbcApHRgAD1#EEcb*I=?#mFzdl0KBBG)+9GlYZ@nnG8=s=R2!YGfBsot9o
zV6>@0{TfMcWDOs9?!(N@kg=Dh(M^ban-XJGFIvwO^7VVOrAXz5gSH%Gq>ds=G-|Z4
za=|GWN%tdxVsJYXCPgK?J&i&NvuHo;Bp55FElABjA?ZP>#zicWN3&zIi8zQ%rc_0B
zU!`2Ek4F?G7jwg|D?}yQ_xq!=yVBR*M^fax0cH*a_`48q#r$|RqWN($oBNqh#$hkyA
zPmFJ)Z0R@Ipe(gm&%b3*4D0D_oRykVj17Il3BECZwPZGe88?WfuFaU1(J;Nuf(7wpUVDQAPi)t-
z+~?*9IoE+bMZKr3i?0suGI1FOL`y@9S+-z0zn(0A?JOAkQEs%wwgi>5#
zNcp}=a>pb-?cx&U2TwVRSg#2TemM&-cL)m~Pdgn9gIB0uk+IusqrZ)LcaM|>ItgQO
zqm3c=cx@PyE-BRA22?72^3S;9o6A179^bt-pU!x{w53+qq)D$aj|r_EKs;=6#FX`*
zN9aN?Gt6nTgASrycU>aDCmX6+Ubq@F2I-u!z)uqOoG45>OY%x3Nr#!&+#p=88ynm;
zx^Fo#FhYX2=uBl7jiF7HI9dy=sDuCv#!;1frxljraDuy%s3
zaSx+(f=(utjM&$PmKFSaD4D1>LD`j&fuYl)%CUBm&F-6j@5JcH<~mEcD{$(LUp@2G
zvW-Uuo;?gguuicbhm#w0!vn9$3C+_@uS9S^_yccsinDZJ?a*EuK#Z|UGc4FWEanjh
z_jks@NDlmwervh_ZaSEHMemIX(@$N2m_K(%Y}ap-a8hc!dbSqpJK_yB3RVm%
ze0?loL`ovYvJw2Y1QRmP26GL)2E^JuNo9OcWqcZAVy$Ks4HpnmPRb+1
zCc#@i#&EXU>UrSGO+rb{Z_4T)#WK=2cZhWTtv_I&;ar-oXRKOy?7
z*^L9^FO-ZREhifawsnvZI2HPD8iC!J@FB}r-QON84UrLyAWdEX7&0xE3z#2dm#}q;
z3mEPnia@6q)7bsjFm@;)AnvpP9AMnPM&hIq@dCpDq?P9t&_3)4i(`a5p+O>{&|iVH
zUI2Idekr9Hlk{O>CWwVjQ-GO>erFmDqXu>dmtk!>VApLl2j4J8
z!nA4u*q+dOuhRrI6`xmXmXD>DXu;X<4a$0o%c+}oCo-&-ma03&n)-6oXkcVKR9f}U
zxU0;oP3kBzx6EaohgMo2aJa0qRjR$5?$N4~xRobMSF;4e4B=SnQCoGqRJW+AO`^B!
zkV}itDjb|u+E~4{n!~N)W|HsliD7bRZyUqpL}reuy|oJVl7Jso6f)+l>45vNv{TV^CqUD=T8MfA}yg8}94mxNV~9R^VW;bD!FOz0|%>
zNO<^X`*#J0rKem&Im3aPS4m-s$@Br)vB>C}K+c77wiCcbI8#o<+v;T*7L49qBE5BW
zRnW9JM@KXimZzeRo1Nfkb{T|q_`u@>*bd?f>8mth#bou3p@uxIU6aqzxxiuurpY7V
zx`_*S@|bkLJh>y-%ry7}_IqN*Y`wezp(Vk0+!*>`Aiu(#q2eeZ$XaeZWS64h8*vBt
zZYa)1{`>j0bGEdz9^3=tt^nTdG?(L(+y!&6o}!d(1SB6w;(LOEoe$(^{a7DBYiBXT
zc975p$!B~JYzt&X61Kf+pJM{HJXtok;0dTK2z>HST&jN8u{v?jb)mSXNz_ez#v{oF
z2N$-Cm(XiqtyrZFQKzKXj^yu5{!i3keLVuesv9xnLW{?bXkz%*lrc3fe-sNC6gTE{
z7+3pFKt3^dcyoUKZ~g=-)Zg-3mo%}cYhP1j_lrRB-=|1^4;0jwYQL`X{1;(j9dT{w
zI);dlL^x#*gdSYcCTv#C(It{w84`bcjxE_hBHd=}m;MdnQ(sU|{(jJY65xzCL~
z=a#HU&5TlU&c#;u<3+o-+i!|(0N?|}09q3od4L=&A^uCy!EiDxJ{d_&iVc>ySVY6*
zWaO;$s+#4%IK&oUDldr>sVRwpugyV=z1-NIr@}?K98hpb?=0VlKRLzb@0@CC5t)&(
zY5;Xm(=arnJ0p8(=~`C2%9xxel-mgULQzfh;q)W-&R@Wd`Nx7aHN_
z5IR*@RBpeNqH7-miayEJZU_k%w`R^yF304d6dOUc>r_o$H~1DB(O*N6cp#zpBRx{N
zS+duQlx`aE+;K#Oh$cSTqC9g37OA$V*37PJBd?Cn&p4wpk0`rX$GHf9xY{trLbj1u
zA3cg>H{KS6j_oeQwr_5p=7^ufGUSkAcuE2;>$=xP?tz8$N~ej%}Q-ZDLqCpV~a-8j0^A$dpJCFy(MO#
zT|Rtyo6WbjiH7ynO{PQ2=gCw=6O(&LPVNt&VL<-W38Dk9`<*aU0sCZ__ha^J_M`Lk
zr2JP03#q@R4dNcl*5SCfkEi|s6hG3nAsAtVgrObM{*%Ucfg^Aq6hJQ@vL#*k2obID
zK%swjxV)qO0Mac8LAVE02%|Iz42T*QL*+-0sfBiG{T{bG+%gAzoY2^M%dQ#SvR%pZmY?YmfBr2T7SNk-FoI%Pb6?2b2zN(w)@52
z2Wn6+r-+T*Y>uvH8DI~qMKbI!k@dq-M5nm(xr(%Gc|2Un$t1+I22b|xd^)?@!^Op>
zh74L0HPz4(^>5RMCen?qhv35nI;#O0yA$tSiJK}>-Wdl!u3x$BAoll)I}nZmbl}KUz?-$(>t+=s5rVzYR&5;
z&BL3md=3?pO!d&k>2e3iL}k|E=5jEzvkx+1MCIweQ8;CiW)09$7Q)w~Rzysks*%#n
zT4z!Sh|3KLn%WK!SIR9e#$=C1+|mF1?KFw9H6RPU%uHdJ%!uj{C49xV7hzdx>{NEk
z){btF$j?Qz18|0>i9}JWA95A&V&7ziD+;)3IK3%4$UXh)S=V&DucX|m4@QXuSt7UD
zfweo9?#LgGknXH)nQo-qp@q(h=Q^++(|AmT%5Sm}N>hLcQ7}wD-83H?a{R<>af915
z5C8m)I~srT>ncI7|IdN3OzCK`P^0aW=lUJHHsx#;C7_f3x)!_?0p>W_CBd*E47j%r
z*}8M4@^|Kg+Zni;*UY5-(Md*Tc_NyQabS}pV>S*WTwku4Y7B^~4Ot7pZx(+n7QRqN
zEl79wF5=zOP+PYCr2oa&JB3%;rCXq3#kOtRwr$(CYNe7?Y&#X(wr#s&+fGjY?%rqj
z*%#+oSL=R`?|tW(11t}nmrmD^4Q^&w^LYs
zIMNmwg@E0&1z$CvWvYxML-gwp6ee
zo{k_vIVAUZ7ZrNRv7`1QUG^jGzew;T-J!!EivZeH02zL#%Q>W1nb}|1K}Vsu#@9f(
zB%y`Jt=I*QaMgIb@4&CojH+cu&xjcKFJ`|8kL4&B}>(^mxP{+#^*1I>Xg#cKr`F_rySRx|8WuHIHO(uXX=EHXMm+0?S;
zNUG)Duf1!7AmP%hy@76ThkJqlnV|n3pnR@r;IH4Gj5ExXn3L~K^?SkmkwTCS`2$d?
z;bk~~i1sz=L@c312o*#U#N)r`pXHns-^0j7IRO?5YB%Rrx=R_>6Q?ItB<11${ZLeS
zMt@vY=T@<)^k)#t%*6FkOAH6NjAasWYP)tAXKUOlm6(Yfb
zH?Tb4ZhwUB!1Eg-;HRAue}p{}`i<#Nfzv)F@jE8+FW^VdSUQ2JJrsK1I@p{(5#DGR
z%}^BC6DjxS8h;7LaEZ*17${7Oi1~9sB%T2EHY`8gHVfxCeva9=OXLd^J|G9>+KZRI
zCxn4|X2{m@?^TYE0}dl+Mdnd)u~Q_X+bw5U6UGp>R*5+8Fuf
zz+piJ*Zfi{D{E`}sDM{H3VIVsqIq<=9fCvTaD!vP6!PEuO*Oo<Hs
zu=KFzOh;pN4uGl9*#jU@llpx<{K)goI%4n={KXQoIKF%C%mHv?L;8A4?}4WESmb_^
z$)nL}=nm@46Ez18w`+{~XE2ldOCVCkBU@HM?eqH5*7bIcE{L7kVgg%PIho+a=FCT$Py35jFOdZVt5l5b94YoViO;x&YQG?lmq-bGsaPiT;m`~IWLj^MWYCt(lN
z7jbA_uvwa|<^XDMo9I4`ET;{nLc$Lq5??@
zq?NOhKNNIE+$`m|t%GH*7bu$5b$_P}S2RVY1j!|HV=KJSS!7EtAtw`d%Pd6fz6}^8ZrbriYOl!%r0^JpqVAuy
zg~1$FA=VF~Q(ZnUkzM08k9bD!qTA(RT+KOD%*kOHr$*W`t7yOGL-Jdh+;
zjP!G2kAnDTxDdVo%8d)GbLs`#nUaAl)YEwSlfSVigg9}(K2moNLuoa6CgH9|OWG(a
zK_~Igs4akEe+Dn){@e#BNjb7x*sz1xJAC(1&CFDx%3e)v4Syf&yO1c4wiv9?&W!{T
zpf87OVpKy=>>XU;=9$K;beo%K*S#Zhcq{eX!t-5kK;T*d>8p=LcCA|stR|t#i(BhG
zojj^8a_6QZwB0du=N%y?f;hYXj#q!%Nov3>T^+y$A5sEH&6PHi^y!m%<2^!bC7v2}
z86?)|+ht_1Fp%SRen53Uz|CO!5i#(<45PrDgsnxrXu2e#!>!`ZxeodhTlA^rE>2c8
z)W*7U1@%UH4pODdVNe2(OSyK_UMqbo;)^y?cvk55DTAPQz_YLOoTq%%oOAFH5Nv!6i74GrkgZ
zMdP^8D5+G3MfmAMc1n>!{reQZyO>7ISi|s4pZZRbBZ^7$ptMh~rd_-s`{zn!7{v0c
zV#6X;;p8)6>GWJn>ifx5njt~d1Zz12;6?!cV^EdJxIVFdVHenjn{5;xJ{WJv)k_>1
z^LBsR)-tth*zDk4Hk<6%<8NC}@~qPQQl;r$HVLvL%PDgD{1+%P0!7{E#oGwbnA|w$
zs$nTl7#W-_5Rh7nplM{5>uB|?5qRIwIW$)$&5A2BCKFV-`jL`tWt{yMNt;wxuP*=>
zu#ClP%lpVAbL_?=>0`kZc9;=L5m7+W+lCh?xbF?lhBVeQ0qWY#X=g7DMeasjDiQLt
zcEtn_c6V80Ue?{9EGJp7oP19+Q}x?QqF+kWnBlw@+vkTvioVcf_fsA*{RgGgd{9QP
zX2sio_~IVN_|)bzO;UeC<2tED<}(B22~xx|tZ}CB#r*6B@AEa+6x+F@v79C<%A!q{
zj6$=^R-Goeg6DYfHfqNeatO1;jth>w6X#vh_Q74=A@cu^-XtafNe5scKc6zx>TaZ
zy=Mep%pcMWE^8C|DWIC1AY8!}keVrEWpR2f$<3q085Jl2}4&3UITXi^-pCC!7fv=prA-y~?y;`i%!L|TC^8`(kI}Ik>
zMIFpKja{|mYxQx(I4Lp_jiFlV^(BfEdEJ^->LOb-s%wwbYyCixDAq`m2dj$Q$b#m^Fb;&yDjsl#e17{Pp*BX{f+H6|!MhhVJcHs>tLWek
za|i1zMX&1YWtKUE5mtu(gZB92fL4f_6IDj1dWnGqQyb0i<|R||!9C4sAV(_+=Rv7x
zXbiM{j{VTXAe^OCq)85D(SdjJj@H=n*ub>QRUPHU%BenTbv>SFI49jFM)aJKfyj2L
zT^+erhkR%#=fFUsGGn?$6=0fUz+H0d7x@2fjsKLCld7~Uo~6jk081(9{FB)7S%lG4
z8KDc_S`rE_1Jj@@T9ZVnmRCS21&2)_+q9lbo49H2A+ufm4B@*YL?CLM_fKd`;?0D8
zB^qVKN>RPV^ugN{my7wgG36-bOa|DPrv6m^R|Z3(a2jhCmx$WfS$JvKQ#!MugLQHc
z53C-1#7tG1`0rF!d!`YE6i-=TJlyhga*gJcZ-)XE<7_EwpaTP$GpABXjVu#vrcz3+
zEHEX2MUoAszs3XTJ8@Kf;Xu$?G
ztv-VTgNJR6XS~b&*TTkwxXMzUdTS-GvMt%3UgWU)QB+y!t(n}pkdMel0c8H(y{5)^
zuo$RJVurYqIG79brLlfrK%|f4_{cVYf2;-*F|)m~<`7|(QVhL&y5*XJ18D!b7-H7V
z>k-a~+fV(K-7=p$QB<{qWV9@)St)??PD+>@FbN<6m8z|zA2EmUgSZ8(4MvKZP|$!7
zRUuNr7vxQ_j-axkDHh@yDa9(Po!?R26G;@VH5+!MF&3tf2|59Bk@5G@4x7a|HM8e(}EzR2;@NGru@U{rO3pBLIavA#j4Q%bJhgK{{POJ!OXK^WElT-
zex!xFO{JjL0DBgn5B-+MR2s{Ceojs|kfaGy5Fs+rGZRuDX;DyOVk|U~zg6voWNK2Z
zx#f6Sx-}hh#lWr3ZB=H)h&Gp24XhfC1;BQ4NMD&rPWeK^Q-0aK)yOH|h#9Tw##Bw6
zji!}+Y2ukXkfAt*Q$#|4@wt9YJ`RUr-}pD{rk7qE%~@S;_*2`QgzCa?7+L)v2RN2O6z%RkjQ#KC>!@fIJqg
zAJh8M`;K{vMrr1ly!nPZ%>9frZH~bsTZowN`C~=H`jY|Aj!tHv}{l$J1>WVgChz)&D?%Z~RmJ9|)MM
zOtEUT0>}j7>A24HBgfS-?$dLx&D73?EL1iU|Ahe+>Ncr=FyKuUiFnx865#~}W3(Yc
z9!Y!20^3f8JR}zx#1v$+kROpnp8hz$-V@sena8L9tvrDTS2+Onty_t
zbx(nj%>YqrMJT?}dAw437_UDs4f{7W6_6+?SMTLXRjlE<7qh2%uG=6vtA-c!{CtAZ
zM>b<8sf@(`3i8X-*!cFF+>7tDEN+bA^>=8Iwb{54g7CJD1oCzoY=S@(BH(RuMf*VI
z5p-@b!Xd>$*;6|5ky6;%OnC;IMreo_ChBk?dimRX#K$TAwOJIyNd))GuR9D^2S8Z=
z`Ir6*RNR3zbe}>J{gm``fXMes>Y7yupH1i$C-#$jpKhIJ?Im_w{ETZlUfdI6FRc2S
zAn$^+V4k%2_z$QQkO-y?Fd<$GsN!&zu04slz_1lYP*cK^{o4`IY7Bj7w~>#=&;Mfh
z{(*?|0GaCgH$?8fZ|FBPAo%}A#ZLwh$dsSg->6ut5~~W(RShC81lO(#u#0Sx4xlnt
z4jgK}aHoVBr(az~{^upgz;gzJl^-+5_j+&u<16ZB!o3%|lB{7ht^UaOi05uHQ@;D_
z^Buegqz;-`k`j`*)DU`pE**-fkT9|V*IXnO#wa_N?z`IME|!RZ;k*RGdQ5Rry6kwR
z4WKpJl3m%KNDkH-4V&FO0cy{)F}3jPo8xv|oRGC=2D?>HV{t`wO%SNQOltX1ro-Al
zq1Q~ewk>O--{Q0ASzQu?gn{Lw@4WA-sq~}Hb?HUaW0A8zf>VQhY15sl=vP+<)afP&--sz7P@n|&aLwG5-S_Z4_LjSFBg^Pq=9=CNR5iUnEW<6~g~Rz?v*snV_-_jkY`Wilgn-v?!KE%G2J;;dvjny3>-
zz7p&ny4}L!T1Hzw*%?J?Vknq7+E$Va)X3%bag9Wd@s(ok7lQJ6AqR@0og&(
zuOabL9?k42j#Z)L&QG4s6l0#vh>Rvh+D+^k&~&HTI9VDNwNMgjh*?Vxmb#tJP~A>p
zT^;qOEFpXqkEQ?jyAqS3jxY`gs%AT5+ji{DF0wkP-LbkkE`)4Ulr2PW_gXl4Uas6c
zzkJyvOq1X0=TL)7RuFk_1v2P~Zk9`q&-A#Q&2h%Y!C}*>sc17X
z61@B|gmi}R%3xT)cO%e{docI_7$jQp8d5>iHD@qp5kB;qfJ}e+irZ)99u!It@0uYK
zy`CT0%r}w4VnV2ZZ$6$(NEvr){#G^mG$4<9BIvR1`kz)3nGo4i3_?MRIQgLn<^}2#YLPAG(*va-eeL-HBL~r;!Ecr`}(thCAvU%yKxuW
zc{zHs9I5uUN9QSi=|%arbo-N0(8ZdLed>f#E$6w~t~pdC4|64{>Cro#Zv&6F_TRC?
z0=M5HmjLltRy7+6E{kF>oOib4$j^TMufqX7aZ4AESp)Leww*-gSUi8Au&t3mYlMq
zjg#UE2aXCie@P)3rTggYeMN8LR2!@K>LxLN-!O476QOZv*i#xH)FcSnDTy04Mr9+c
zb5}{>9Ys#&+J_)0b@5renJYAK=j&d-9Zycf@fCCU6t
zqw|G7MCWr7yx&YGOr)Q#)I879hD;+U7=ss@7C4LS+dX_8T-vZ#G8{>d&qM6aG)VYE
z33UUJ_ffPXh{_m1fR2#Szpo}t?!48}v+?9Sm$SH2^B@kU$E
z&`|Nl;QmSgkbIT^rbrEhr#Bwd1)7GRGBg^1pWeRdtkXNu7~*?W1+!g$J}C1P});7
z2@HFORDbpGp}s=@`i91<-_jD1ZHf0%n{9Y=D~oSgLvgB)#1c$VR>kq=)^tg5{3K`p
zNd&K-@WD}V&4a&#V0uHL`YslDadj795jLt2%CRjJNOq`lKa-NP%cl)dN?}hD!(%AW
zvSJW)oy4ZA^?xrr*&K&!4&M@t4AhisHDFpmp@x;t#uD03Hh(tA)zn%!kmd#Eu53j0UTWCaIJLr{;!B;iqjJ&?)CI)O
z1Vj+iOSOQe^m8H(`H*!WAV`(;^z*)aGOqPK`-e(+-dkcqkX7_TkSTv6(g=|6^glxi
z@Kf(N`O5YU--Iz{Z*NibKa;}z3@6Azze!`vF6*i#%1vWsvA^ZGb
zmf>}G)e~u2i+VvssV%UWMSt`tgX)A+0IdvN6
zt=5h%S_9e756;zw(yO(@uR1%uJmE|_7sxmj$U5iGkaRCl1|c4G87n|uMl)f}cBY-g
zv_q@mHo|Vo$DH!dvrq-bkuPjh$iCp**gUc-j&}8UO89-BnvSm#f>LC!4FYIt*CbK7
zX|NkU(&J`#m6zkmHo<`GWG;-t4o|3sZ1n@Dw)4W`sl>K^@5sZFf9Dj?K|tC_kBp;q
zBw?;tjb#3_iY0c%G>>K6O){fcY&93L<6^ItVQx7^w2Mm@CA;VEe;dRl8?8aXCUP+@
z3tOr#K;lF?*^q}onLK3TPzTt+nji5NVYZVWn2t&<%Z-C6+R-esAHF(i-E!-k&$Kqv
zavMWZL^opz5dV^ZO1h23ziLiwSgR~YDceEZIAj6uLW6Py*&NkB=s5eam>uc^E-5Rg
z;(9^srJm5FI;hmXfJBzhQ|dH{SVOg@iD@%E&&hyto?N)JZk!plrUY2zGAmafru5n!
zTE$mU%WM2QPeuEGDMG7MN|0+{yQszkzo_!jIEu<5XX*kB(GR}7iT1a
z@MX=?pA&-Qyp>BfiVA=k2ScKv54C=&hF2)#gt~_4g}@wLG@Ot=sdPq_W_x#c58S{8
z{^L(lcuIX+bfxn!Z4DLGNrUzJ`cqQ_Bqy@oPnPN$L=hD_nC&-h-@p%E&R2jA^`u1$
zU8PT!oOBu%P35EI#-F9vo^&kfAtBuO+2D3l-0fkW8G6Fg<~)F0=JKML=BOt+3&?;S
z9iNBWg#h7hdgReHZ+{2jp0~Xn0OAYEQWv)|^j9RUIi{)l5EJfUb3gH+X-8;^=|&HN
z*t_JA+S4E^5GGdNqz
z!LD58!^X&heKP>~0-w29w1aq0?OnM?y}L~Aqed_Whm_}o2FqdiCsOt3Guuy+?WIBO
zUy)n89?Ze9=r=y-KlQ#v@`>M^2Svx!I3StnmlGDCx5a;bgK(-{ciWVOF6_BHlH-~K
z36OGw5ItSgBi|+Hy5(HEg70}YqTvXm;izZSePdU)WC*y_M?s-@*>$oN6?B9Lqhx63{phzoUK61jd+Ia$LCSDhtoS9Hr3cA>F{Xfv<;-=>
z<`fU48UqR!AehVI)OBzmsB&C+@7tR*GN)BJs_@!UUZ@8a+`<#YJrtm^Hi^hvn>ygT
z-L#0>xTyO3#W0$Eks(&+pxdYp@{L}W)u2{3_v>UvbW)S+engW6^{(_7irN<}4
z#Vqu0vuNUvb$X{f-X8zycE8$p-aL!}0$^}XYyt4HRqdWM|70efk!$Gn=jkxmm&m^_
zjFRF!#GEi+rf#Z4TVwfx){xgE@#|_Iua|?k-G4L^fLsi>{cO
z1_WEW!%eCW6WffNE4kna+oH$WR5i+bvlGfr^X=bo5;N8yA&`Vi9Iu~Ik=9^@gh>RD
zTDv^X{#ci(H~l2y=7T9ObH*HWsNnH}spIEVryM(D6h27Pvf_
zDrF4P#p%?0uA`0AO6sBG6f3=0N~Zq21HhT9A2PRR@aqZH(ovYR4OB#@UXYs84OAqk
z`%vC?qF%6|I%H{TqF%s8F(4V3cl>sYHo{=yJ9X|pce)b8ecIOF&2+s}eIyS{3Oh!d
zr2yjj6sd*1DZMy|c9Fi*#2e4!uX_>OK=1Q|fr{0=#vdu@F+a$xv8ccub_yWH1Xwa~
z4cH`c)EuyaTb@nuj!=8#PD3c30Pmlkl1>)RTzM^=A4c`$h=?!^`6J|S^dmZkAG)+r
z@NTxPz)rhQ0Gdq87D~Ud
z2sFI1%OjaAt9*`1Xo8?U`f^}uhq<6n;VZLK+sbRmv&;KnFeanGF`qur}sI03a
z@-hEd7v?p_my(*t1PNopY%C)MjY;iM8q4N3t=G6
zggOWU(A$rx7WLkL-l-o%&%O~sjM3({66yAD>R%l5QPXF4tMgw&}S
zawpJ)m#x@#NvQkep#O!z20m{6sR(0YXG;*z1
z#aD0K^nA>Z4lS0P%XMBBqc%3w**OxXVM5yzS;ZK<2=_PQ*j&feU48Us%Ldx%@=wb?
z1O;WBUG)SxZBVV6X^Ky6OSS)+AC}csGQpdpqT1;(sdYWF_dixi7h;W~Mb>pRn=tC}
zCBg*TX9Sy%M%+!~0iwsPjdIdZ-^6d<^RBlm!9S@Dx8F@b<}m!9bq0jqGQtSdU$2={*GsxSIRkJBirvq`!8@&l^%o-
zrK9AZI3`H9XgPreNEyc3gQmpU#4!d5L0#)M@le>=ra-bDxr!$nK
z*HrgYeRPMP2Sh*5qj3P&i7Un`f<+ig2tz%Qo(rQno*~zZKSdBQ1@J+=%@9+{%otsh
zbm>c#Y$pX_WyeCLpNanA&Dix_Te+oJ_o*;c$UzgTp}nMFaB~2Ib5lV=jR5Q4%shau
z$2CIysxhY&D|3sb-K5J}ycr$lW!9b$$SFoD
zNzXFXGp?{a$i&L;Bjb=*W|GY5JG*~@Bbh3M2PT-I4$5dKO8fJ~nFIQY*Fy)J;5ShF
zG-si)4d|DcCcUt<%;zv9b^{@LK+la*?I6SF7dpdf@H&&^J*_aI+JO`0UimB!{EirI
zp1m{KWs+a93TKsiQ@MA?psJIk=N=k?r*K}2c<1v9KGu+r$`X9t%4M-6JLV6->peof
zB?9-^54!Z&>704D3-|;J83-}mBmGGfnLM6=32-2sof9TbbIBhiG*OuILK1!ge%>b)&Qi*Feq
zw*h8AByFkIvPHb)7l}&iOs`)kUow6*B
zS&y*yrc8!g4i$vOP<`N>!xy=+^8do~)DnOdp}@!&4;T5se5--s2$CuI81rw8uUSu^%dp|uqPy63iaE`oce_L|9(2{
zz)}5)Qo4+R1p#hYk<}n(XPN?tSjY}p8uurK*jo?YUUHS=9GHVR0X4(X
z(yfUT84M0I!%H}CjzuYJBP*12#kJV~?^_LSWxL%!W
zdK}{_{B9q@)hhkK%Cn6x`MjuBSj{0p&v%fcXi!kmV<937S22@En&9lQOT
zQ82buZGNj1lo3egsXqtZ@1%_d2%RUa$r$^XErciN2`u934x#1mDw1o2eaL!*x0z45
zXECBuEWvHCx&Sv@%FhdI!=uY(FKh*)ZT%Mm|Ie&dZwFrP|BmZphD_N`{}#(BS^-0)
zD4Kn{G5+Z>`?N=1F>g=wZ(K_!TvALC#TnT8F^e1_2WQ6y*|<2Hu?a(K`}o~sCi$V_
zdpCMCMak`V-N=IXMgFkS4uxn9Wx~wkbIB*r<E&%uj?cd+rCi4#Tv-H&mWsS
zXlGlsA0=zmAUgwRxZV{D#`0--ImZ?$BG>C>{Cf@JRK9K>=9tv%yOw4v8S-Ysd%w`u
zoTfC&sQEyMXf%1GL~5yp3$2z}yg?5u?mKfL!PbtKGMtAW!LGF$W!E)M!;ipD)2y=&
z=nE@FmXXC_tHaC-nozCnsJ4{5%lwn+fJya|$Q3
z-%e_VJ4kdz8a(?4zfmeadJ3hY+?mtXTO6h2diX)D-lfN2mZH08iTqNN1w`rPy((X3m)YU~0M9p<
z{8%QqUSH6NcTtyK#P3;BF$X`e^ohiiS}?_c2MaNYADrYcJtqdpTU
zlK%U&9(S?x_A3!;f3&M!!Nz9eDZ`ZmiEZFyqV&`#m3tL_UXcLW|G?RLN=ka(1%B@j
z5s4KH)hlR<^ubn-bT^6GE1E6A$sCEPzh5Np0zb-{%u5wX#9K?~RW3g-00Y^9H{=MI
zjtaHyr&QCiU&(mM*{=$;)9D7~T4?AB)v2#vvk%HIOp)&jjLhAH-#*M6MIJm59@WqY
z-k=}Z@*ucC7?g!F*fstsBh-Z|l5;o>)Uk`Gqh4*ha2>k&M+9mlop7=&1(JrIznhd>
zGG$7C@Db8f?#YqjW_d;0YKNIU#_?sJatypS@851BMU%tFr}n^B!8$H1%UM-v!ISX4
zFB_gc(Mn_IMJ_vK7f7wK#JzX*=~XD{xpX=@D2IA={C)xaAGnW>`dZzk&{+Yq0sd1|
z2uVwt(V+Z?t*Mb=C0JOqK~1N$F*ZOLR4jgOPW{Z>1xkj)$H^m5(SV=(6Wk(m_NKDS
zH}^wuEid|~^U&5lXLdV|etgmItkF%MX}<5qLf)f|`j?~bVE_9Z>Ek9B!*dG{jYM49N|Q#BMOYrb{5V=ffMM|ANG
z7D2f>ENv!ZZfcm1hjJ-Gc=dLd1$3KkTy*U$!IV}oE&=O@b>@)kE`Xo|>%IKt`MgAo
ze&g1+d%~>qFsZMagwctBt^%86dyGb!7jS#eK)x(t*W~
z;*FpP=GMHrf+^o{Lj){Ec6zuV>T%rUC*9VW`;XK5?g6|Qo~q>K&Fz)@;B#IhUBU!O
z^+deDnDqG0&h^s*gIyK2=#^kH-M*adza5m6EtR{V$JFpUjDY@J3v&%I{2%>HBF06x
z#$1hYXAAMN?qe&IsNmpexGu0EI7IL$hOVG6@!Nt(-7z-0%oLlnygu{q#
z?#q;oL?k!GzzNDYDKMggz6&BK`xU>NBS>h=HGB1_d#P39B9Nal(d;JNTaToJV$^&C
z6arg3S|VWi+5z%d{c%}9SlrOQ@(eoqS!UF$^>1sj93>;270t#@-Svzei5nfX!8NAv
zaz^c{Mf4uY`()#(RUHr#9;$gfWf+uESy5vjKlGB*QR$T3Jhino0|G)1i$cijRYc}V
z61c|94z1Gnhh^(#FB5SgaNG+T97|w}9|ElGsTT^}6#?ugrnlxIZ)+g;Y9^))osKaS
z9yRxssK)%mDPhIYru{PdBD!kSa8FC~qcgmjSkeaMyBk0%ZQ>q}SR0amD7|8{IVuDC
z?X0aHOl6_ULM+pr8JYcfSeT_tk9`A}l!-OexIISls&sbQTj$qH5ZGBC!X)+cB&OCN
z&4oR}$pNkN-87MtK}J9fGZgy#Mz2cKAbts!MY9>R?Jug}=lpWQoWdp%4DZkqR;r-j
zxFQ^#C-B=~R&h)`;Ux%9Vpm(1=H+LQlj<|9v(3SdK6fMyL5`IUcw@HD9t~6MmGjp?
zc9Ci&-}hy`z_m9FV}m>syxP^j0!TU{9RYk#h=3<>n-!Vz(FIW6=3sY_%@k-xsks}(
ztWr1E$)UX)`19)Rmk`PO%GVvKF9V|LU)5F*aD%sWyU*}YzA^RBz#2Cs_B;5n@1mWT
z7N=I-+b-{?!`{@P#n|PUS)%dA(R=jXmMNc&e-JwFZG^28a7q^ySfUP@SR3CXn7~2z
zpaJ^i5~PL2R(G)aaF+cx4bW0vSJrqtPkt0_0h@9Z!lpOe7Z92jR_^c)s&ryV&*1$F6IbngV*1A
z&I1g3bh@U*V0T)+Vq%mYMvET+|5};9i`XFl?H8~!m!0_Wy#jGT{#%3auN6oy7ZT^2
zaL~~}Rzm%R$3W`qC@R&Pm_by%P6tnuY8|W5jYux{#u*}k@5No3*q-a2BRC#}@TpZt
zsLb|0mS|kF2#!_7MPACRw=n2(xbmaFK6`4u0y?Zk7DiP0*5=>|gGfLRvV^}-7{|Xrqbb7W6OmV)MH`0(c5j}tx%iHqNB1E)t!@}&ia6g@Q)EL
z#<(=pKnnpX7fzLuh6zSk1H~HGG&4+VeNK_D?nOM+PxY1sTuwZj=oZ;jqR9!TZ)wg@
zUR7f;`Ck?=YxH2HC!hc~H|b$hdOR)}B>`K?ByFwUO!XPGa_d-JHwC$Xk@HvR4em~1
z2-xyURF9&#D9psXIb&>$-2woEe*EBZ>+Izy96L-wQHKqynXF5o&X~%e@*LgbUR{WD
zo^^?@TtdXsA|f|k|8XY&{9-)g2`S=P)e1aGP$47!wh>S%+eq$(~E{<5L8%Ss*CMO%Q%AZ~<{`Ptn!!l-&
zqPWZ7k9;)(9(#QRv?8>ebQqVwHE(&yQi7mLibv`L(|#2#rLlW^9%OzIJ;jrigGbQ58Vd&8&uLlWUT9O^u4=}
zM#&_pk7G(hgOJTVgU$WtGn21Gu{9g^$h#Z!7Zx)hYJv#!%3B!h$@(LcBq|bNXjfoc
zKzu#!!nG|IUU7zq$R8(^9T*a~4ODSFQ1hwe(!&Y
z7XG<50~bo+0()SwC@CVayM?H{%>jL*!*2`mj3Y+2ouSBI@P(xVts^GRrB${UKXa$Oop
z{5Co)pe^GwcJ-1MZA8)o1x^V>@3PCSaa7brR0bGzWh-*$wop|zi5W9=BB+xCr(&$?{aoB#ry*@1OuS)yw`{usiLp>*&CIe!9
zuvX^LI>~`7*lv}4Y@f+Qij9nsEf9zm`1O;ji{`RBGeUhYbN$nr4CfB|g^3
zqUOsg+e@Q(YZjXJMJ*~(6~li}lgQ^eF(~{#lP4smBi$9Mx|Imo4ghkUR3_;*8_M`J
z$?^7O_$gRpVRgB;Xma-25_-ppu=y^pq8br>1qp%`>&7gRi0FMSA#cD1eUf`Zm=T^M
zjOWQRm`IVq|0vsvBJfnW#VtGnj4p{o9}WKvmx(LK#nw6D@G|H5$O(!QXfN*_B{#$~
zbK`-{h^cyWdO$>7*XVZCn9<1^vi0gjXdYv9)=-|D60y`10P%LO*Z?v`P=i*=>-iX_
zVQ3d6!Jvmf;am)-l5QVZz1J+>BpP9D*3P6M4??3Lt3dz0*F;8RR-qP@G{mM!sE&yX
z`##YZyHo0_>siC|XPz8?^!9(i0?Pbydc3uM59pMajOs#Ib_zTnR#j$^os;94TR+ju
zBTqQ*rJI}cR6oi2E+fAod4^Y5c+HKTFd(_hA->ZX#SN&9mJoGpUz^sN8+kUQ{RI6a
zX~12Rr@%P{0>?uJ!4z%)7ToT^^VdGyXO`z7%W;xjS%cSZKhFs<72qcNf>_~s{)d%8
z1cUy6M+~v7&+%ud>iu8W{S#l&URMZqZBgLF3#nY_09kWZBTOV1oP{QLREMRYSm<_;9p;=Wx7RF{n%(M
z_n$gTpO0H}MW-a@yKH~Zp=fP6!FSrs{Npsg2`Cc>%!csaJLY>p0d~iUVdc7O(Dch&
zRo55Ne7ONibuH~C3Ai?y=^#q04~aoO-g1vv$r)6avJhzEg$96J%6Z>}RaO8L2S)jc
zCPf!@O}9Q_|
zTr0W|CJfR>Z)k8kQbAnUHvaK30-H2(0HruF=78Gi^ve_>UeX$!VJaU2vB={F#?swx
z(Tv_z7qp8WMl?#6!t4j*#sC057u14NtJS2E>Dk2Eu3c6i^)Q~Q)n}I#+s3||NG!z(
z@)VxwS2>+1-rh6rQ~nFItyuEWD7B%XocdmY=Dv3T2_&T0`a@9+otGRYn+QgI
zWDKmC8y~sXvM`6GKFRc8TlOkIA)`Z^tM-uu!>lkXv3^NE+N_R3SEMP3;
z4>2kg-3$m?FT1!lSuZM6snFiKdwb&G1^ntJ@-qQB`H;u|%0eZuu52-sa~p%$d0d|U
zx=d%WxbS>@9K9g`S(%!NBBmgT3lGsA2C*>^QRSmhG0{qDCe{qh#Ie!#`whg#pgk^t
zvRRd>lWDoy^_Q9QPEP@hlwEM0@zT7rbs*XZWG&7->Je
zDz)b>QmjWw6%2mal(kl_1$#ba5qT^-k``dS@_Fz08Qu9&8y&+3)){HFWpSttBURIY
zM`;wRWk+cjkKVp=DwF=PK
zl_nUUt1I$9RIFesvFdNgRbxVB*)#Jl+uQ<5HFX-((l}t_35-%Lb9!dfT-7cvirTKK
zUH;^?A8}lS8tpMJGDxE0cKuPIrf$Wxfwqm?ishW6jx&`A7avsKOqauM!Zz|6UR}_8
z2sY5j_PgHC25+W8fLRzd9v
zNsR5#3B#A`>kG$+S)wZayzu?w|Z_ktg7I+n8Pbf
zJy)MS6SrE+EZ9&M_ttUM5zKLtxvb3Q`p2>Bx${K`>ZUsYDO4d9A8T3g30jNnI}5~h
z2&LY|ptma)PZT2xFX$T-XQsnvn6CL-d&dJn_Mx0wftbQQ^}$TStsJB3Q^xtICcC;H
z-qn`q$GHO>U_WzZWGNtj`lG%EDPBM8zC7u_^m>nJy%22-;f2Tev=};EGv#xf5_XT2
z8IWdj3LRUsVEy_r76X^K!}1+nTxStwN$!_U)(5Fdn*AJh4aGgBvdB?P&#qid9Ka;1
zgD5$C0cBZS%)7uR>*E6ZZS)Tr;=h85#S>>35J>gF{=Xc}Bj_(@z_%c@@_T;#CjjJs
zFo2TM-TUohE>z!C|A(E0|0RnVAZUqHL)SRSE``(Ay(G#CR+B3d06P<0#wkU9GB65j
zPL67S-&csReGB*As@_T{lg#g5z1KPJCkz4w>t2~!(Wvm4eRZBw|K!UB__%w^0Wvpo
z+e0_jrFBL+G7gI{Lo(4sy3U1&5hJZR?L|RCUJ?aBNa?fjZh${=p4
zp)&?j0O!3Uq%#iv+CXCJ>*T|@Vfqe@PyxHK#J6PluS@7A~k=9V-jQ{;R^;4`1zqrS*rC
zj}GcVvUbqS%0oG?saGqk
zwf0mJ5@7Q`dlpF+1?62#MbfO)%`=iDbZ-{%ns75H(ihLrBGgH!%8W`HyZSrDqw;J4
z>SJ1NVtdj66*-iRW(N|D9^H*2V-O?mba#1k-|%<@v^$90@HmcoG@3*<
zw|ZK_Ju!5yA3OH8*#Pho{e7kFUi}6f+w`$Aa2x1Bk%|4IB4(Eh?<_0N#iYoxklVJ>
z6@AMQD9YPRfg`T73-6r5;Khz3)(8OrG*z&=vh5^m=;V|SK21uJ$Y0L@o|t6+c#I#i
z43F2pfvA0(vVuxh?mW1XsLHgUxtwo0BQl2gchtg}6%{YAN>rpNMX`#(fr1&eYZuUen5c}8;Q#+WXPm`S$00)=d%Y0
z{QEGX14)iL0dL&dk%-{$(*=ZdIO_zR(F0@d$xV^&eXuaz6nb`M8^
z$lRPzac1$fzGl4g*O-?EHnCKIczb(OFWGsAD=HusR~n&i2$$4qhb|=_5ZBM(Dg#Ti
zNgt?}CX~8)sF!Gzxq~3z{h)J4;jV}gGt%~;Ac)!ez2}V6{grBY!UDf+>NY=PG``_$
z{M*sj}2$4!hmAYt9-~_w`)&
zjp&+42!4sXpF?{@w5)7L8Aw|=mRx|!1~>42l-**yHa{MThHr-XiN1)o;ZLTYf^G?X`*>u6p3gyQG8=F>P#51<=_|O}(r@KZ+wSwv
zZddPX&+QSZ8oqaKMC<(slE(Be5kNQ~Y0p&gBLjY@=e;z>r+OCPR`z$T=1n~BJ8}10
z@ubJQaQ<6-pC!m=w?OHkJ!R`g0VAP5k`>L(d}So);#PqKO+v0NMYOY0yhLq{L^m8b
z)muGOs;HQ1v;6gFu8VanKWG>v*4b>$+gT
zD`m8!C$ZzzS9_*%++yy4frhcT04ECe?`Tf
zFQh=jfeJnv))}hVE>st{bE7966HMlxw~!vD*ONRO0G{R5`0&Jf-4Cxc)QSoTZ#HH}
z9X@BojjCTh1r~oLe53v(9s5qG*@Jr;IoL@2uN^rfPngi`yom-?h~x}G1}DO0SkN%+
zNu3xhsnVHbLSgiZ8&KR-ctkAdp$s2wv1`WYrY;&U4kz{)U`X`o(Wzz<5ilgEd60?yK~4!YB6V_W-^a*Iq=+1p@CJciF=p7^x{}$T
zh`n&kqqcGrW-)NH;E3RO8=K7??p`J2!EByNV6VBnTNYt)zQJlMLSAht;T^+U8YL3X
zW7>ZccDSUx4k)9x1~o=!t}wx}g$xBz!C=5YtdJK>cd9m
z17iA}c7(^auk*=$l8SjWLHlpX-7eWB;w}#xkxiiJez(b<_g-m(7L(qa!t&Carb`A6
zoY{J%^V~$W6del(AqSRBlxWSUh8O60OZWULzFuYR5g=a3;df)c^EvC3lXdb+ykKH9+n(C*TV69awcy0_*A>#BiaC70NPq;fBhe+4K36Lu+NZL19MZ$^*d6=%CC|4waX;AKH
z@lV~5G^^YTK8Nvo3UL!b!|rOxSkEMs+UHfqOLF&J*@wweaHEFs9k^Jrp-TUK8nBc_
z313@%ho7T(3M3gSI$gmntkhaLd59kBHV}Z6AvnLWfR`cv(m1Y<8w`mr&KMVIS+KHE
zV)#3(-hfwWI*u_&Z2WYDQjDYcj(j^N)2do!i4|(w9tDG7x+E!h@~JcOkX?^ZD?k*?xH)+1FE(>w99`GIQ`N7<7SqT++s^Y;*bHh>Zkiz{prMhAd6EgFZP
ztEq5G%T_&w;whL{Nmn#audaBoWW4D_e`GrW4dR1|n;kel&42=cjQo>624qQYC%nQ(
z*mCFJ6#yd@C=4DuUD!sAG)X9A_v5LYiams*pE3mDsl6J01or=&fceVq$WD^HkORnD
zy_QCOwT?dWf&Vpgs5yI2J026EOzp0(3PhbQX;hFDTGmlZO=
zQg40&490ZKDR5h$V#04f?967}+D3s=lUk6cS^MG&XYB}x68wyhIwScZ*Lr=8JZP<+
zUSASEDBe+M9O+x6vMcy#QjBCe>&-SjYG=T$gwf7H3p^Oz
z9>iNVTr;gh(<7aw^|VBr#7(Jr{m*@P>5OZ&1hav4F2S0iLmcp+F3}+H#Gm)bxpClD
zH9U`m!uZKkjd@1_%57mJyxa%9W#iq^8g#TnW2vt@_4=Z8;{f6RLSXK7W5czm
zESYdfpW{SXeQ2P1@VU`t#bQ`w
z(eGI{4~I>LO0!^Lp#Y+XGk0jpZ%A)-MO;cBc23+bqVO(QXta>E0cBl(Ipb|8K13kq
za3ZoW25!IW{}rS9rfpyT%m3YqU(I4Vjhn;-aX16R#%4y#!DX#;RT@~IZKr6f`XUu-
z>^?ToXz=6?XvF069(00tH>cPXvlZ1L$_LgA_^XXPi%Y-8>0=K~f7Tj{{#RS<;ugY3
ztbR?w64!ygi=$h?+SXfZCX06gA{a#ivxsscJ#Xte`sT
z4ILXI`YcuU@L3RZaDAL|qHBBzuIMFVd4A4L<=sD3T{+LzXgE9Q$J?w{-p#1j4)b_T
zb8O^t3ZSeaNG~!bkLg{iyX=q)!t09ImS5ZVes7kIci%z1o@EfgbiTb21UHxvov^^J
z{5t^%fEQc{?q7Z*=6Hdpj3ByJ;d+qNO)axp1V={0D;%B|*3GZm(c9ow`#FB)A_^>i
z6q<*B9kVQ;PTcTssJ#M<&2U!!(v7dsi!_-Rf8rCKft`cbuGqVsnTMcQI8@3TYVG1Y
zjGAT=~%%G;6~%INB=<21B9*%T{VI)e|0fDVOt{?vl$CzPeIQs
z|Ld3w;mQKtw6NDge!)yK8Q?wer5X358Ta+ZQ<;4~{f&Cj^%7nsnd>|CsDvzizG4c)
z9b9_TI@8Q#7M#TaGVOPR`5^Ml+LY=Eid!RZ1t4
z1DFSM$N0{PS>LFD5eaV{m);(*ta+@`dtkmMpe~BtzN3RMl|r%Zor`=Y9io+%e}SR6
z(=Og4TPGNF9M2Ee{ELQmLOyG&8f&-(U7J$|*|N2ztfuW2fcje)f3_E;)Yu?V_S7j3
zUCy&8qO|ZpOv7+;UXg@#P(|A=F0u&44=5^gqm3`Q`6Hk1=N8~q+N51rZUKMh+b%@U
zQ+i=RS&r6t3C6c5LZ?{9eBBxAPtPrXz$F+V@AJFLRv>vhP}N2r;}g}R2ll>Gc;d9B
z4pz6A^9>I4v;#tCyFlo{`>bd?K=$j`*4OWyPT;B!1|A8%!kHZdYE^U)McC%G5x@zg
z-m(H&!ov(pcK(3oV^6a)ij&C#%zlK0gzk(vMW|Phlls9Ip)dH_n4wIF0
z5U<={-^Zcub*qgKU(0+RW2;B1W=qInH0ww@pnbx#0p(pP?<`fS2jl&3I_I5x%%lSD
z!dbc=AmAFo9{+N|l$GqDc&Nx}IslrR>pfQf)B`i&?_D)1pr@qeQcUCBt3)LLN^Huh
zIaTUKUFKTEWt&~Ni>c>>91iZ~)U8f8ZK?6*O%*&Q{HsYt@4+2|eWLG=+&3V>0=bXsX@
zW_@I)TY4~>I=T%VOM48uNl>?(TG_Obc66SOZj4G(ZFX5_Fgt&mVl9K_sh%6-1I(Lg
zM3KMKIsD0ZqAR?!(*sN@YdF}sWuXPZZ4xxNvcL|M**90!8Q?;DEy>G{o!evq>mgJn99YFhDog>L{FdJ)ODPF`^$T$9T)iDom
zXP1%e4P_?Sf{e$^|12!q%KJp^wSl0{7PW;L6mWC
zJgi(xFEi3G&)S`xPfi!R{7Wh)gjyrcCMVYE-RMceMGs8vUFnU9O^xb#K4+iN!XGb~
zmiYb#?2L`JM^q#Q25f#s2F#^5QwU(L?|E8N2{R%Eur_7~=)Pf%+4+98Jh-BI&~qss
z3YKgv`GVcbX@^1I6McEUfursDe}sO|C8gfu2fIiQd?tR4y?ilsjm>HzX5}xodcT~2
zql^HeYK|s#hE{x`{r?&0vnAfM+n)eo{Kvb(`=56ug)$aM
z6=)&FFBS+L@BkVGKTL-A0Z!WeA{Kc(y`Y&qUtBk}!Qq&E&2>E4=Gy&#ToKsG0}up=
z!FWje(gu>^ioeF_{ZmmVq<=L4O)@kVspvGNU@RG|>b&wNGi%UEa;z&q8jR0b;Yo%Y
z$DN7qV+ir>6i-c+k14iJ7sXeeH8&D0ExeEh&=~@de;g{Ri?8>0KG_*`hn=G7SCx6A
zYsFUOdu{m-t6b$Mz23pNAtGjM(gniOlr89lGfr6<7&6V&x2=gPk>2L6>pSg|Z5Zv=
znCT={RW?Va~|VOcG*?=O>1A!
zdk5gu$-Bp>AFM((V!b|u5y7J1ZSlb(lxtuZ%8JxKo84e+Y^y`7qIgB)@NR__gRYuB
zv7_D9L_UZ*UM8Z`JVDCP^$H(*I+4MS_oE`P&;I=gTsEZDR2*qs<)~F0c<97*$n18?
zQD8;srQ+-|RW?e2D4ua%R&5q6G9cB+B?=($r#~Wc^9}liN~A7G>CcSI7|AS4>d%E9
zriadErl_^4!~BWX641VlNji{#Doe8bD&mtub!Cp6j1r`!>O`96G~JeLIyF>@5gj+I
z+lZ)g9;UDa{hvc6eG7Oyc_KZFfqCHLm=)7999e?1TL^)VPe)%HC@YruaJPUD0T4+>
zO3LT&jlUYPZMGhm@+
zc8erEwymJ8$pKBkUJb)wI;6fCO{?~{<`I`q)h5Yq_Esy@K*JFwJCSnzPv_kz`Kfd#
zZLNTpjNab@{&-v(bdrRQ4%RX^4QRjw$8^0N$KqJSRH>O0A*ki@(op;^%WYV!J%&Kn
z*UG{~vQU@sD{CbSEajDXYG1DZJEjRki9W6{i<=J$rj4Qez^`hiN!`ZPGP3jQ-#C3k
z>=>wYUR<5zHc*?7wBSkS?RJ?f%IQAgLNd&-&ds~jnjJ@&LiDsT9aH%*?z({25cFua
zWq|mAF-X=R2VLHTA~-vbEf-9#E;4=>bevd#
z@s|0={}8zSha|y|fe_vQAW8c_UW5Ok+e-PO0!B=M|8F_`zuDQf;!k$=tpjYeVnYK<
zqi9v3sF~1M>)WV`G#49)+HOsrmne^tG6nlnCNg;yOfhqSMuj(;I0t?Mv~~-Gz0IFB
zclxkFk_TzE&}VeC!Ev1JIK$C%Pxkt{c>iNp@qf<6OYq-7K1hyixs3~4SMZ|VM=H!0
zpLju5Vr;(wqy^3tj6%FNMp8R4$`a7&iw@&#B+W%=K>pa(1dtB81N{TtgS+#44DG$A
z_U@}2hIFm{tAWu1KJy+2F5JCmXOE9KNo2BdbFYa_<$)!p)~Q9B
z%|>r$-Pr}?wm2xMS5O)y1Gkr+tkPtgnu>qXLhLJj=UuBE4VpGht?Ki4Y34M4iRb(*
zex%_lOguS_4r0QmE^*qn-Ry&0NtsZY&LuMI4<+b?w}XF#OqVE-Tuhn&9l@7pSZ?Sb
zufZ??rWl+oC0u3tmV>gs*ho=Mo&e%5?1l3Ox=XMDo?AC7E9e7y+;iQHuv7MVt9qoM
zNEI1Py+|@xsys}qmaWC=?^^dOs}=`@XjwmzFb30TGs%;}ZM*;TO}D>5XTeTAz8bxB
zSq}C6uKgWDy@ETZ;t@)h#Vb*;AxCv!2ox%SA2g+UV=}ZRPy{rlmUx4Qx2*#bv%EK}
zVM<48TcI{GKQP|SQ>61V(Bu|27-MXwbMCh_0J6aV6yoCdeEn45V?e
z7Fk3B=I4|+@)B$7E|WIfQqw>r?FdpZ!m`RBBTTU)da|t`EvUI7rbe-(6M!7CG}{0GcSpl{
zXIBZQV9AVLxLLxTz96iR*;0fxeMaa=xp+hLE`k76q7K`MV9E5%tla&eU1|8GvipGP
z5!y|B+_Qu2LqZH7;`b>j{OSeyDg?j-c7eWlLCpRA@rWw@Zc)eNf1L~S^9_P>f{zLD
zt-|qtpdsdvlOSc*{NG84{}1~e<1D{b{h2VPCj4*mi5AeL0qKRUg7MvBl(3p5onhoz
z_?*_5A(J5kKOWb}JSCviY;ER2v@~`_oMqC0b-pYOKkrx<(JM$Ni=6%2Q?0x<1eciG35NA5W{Y#IjV=@HOE0a%l
zOg++*#0wx844!kq^en+nBP1B#6DgG%TL=B@X)hlf$@FLX?pe;=ekDR~!tEFQcxsd*
zBO)Mp;*A>5Tee?F*Q*;CexDog?H@?zkvHK65+ms*-JfDaJ<{cMI^iSuP#9UWkL7ih
z;dMoUF>yol<+c`KJMjY7O||d&(jAC5YSs(SF$IV*`atK4yHWajX9oXZ`f>~B^O?r$
z*@^jkH&Vm?S!4VG)^ixMJ@&$L{PFwSJKgeC3=$B3YsyVzi1pQ9mQ(gqH^Np8KlO?8
zy~FvPK=&av+;fW;{h$H)orI2l^q_9YAafaIz6oh4E~VaX!bq-j+nQ_^QC3W$ThNZl
z^akiy3`A`~Uka2fC9>EyD^*k4H!&k0VnVVRf8X#%5_hbt8Y<5Xc^<&Gs$g{xrbq1@y|v}H0_6^LjE5lA$wcOsmVH}p6s
zPt0N+40ojX=RNZ&dV1;i?&pZd6CR{1wj}_%<>`U`WoWojzcZ)#Cx-DM%o5QqE*hqZ
zXOiX=9}Z21s4#?aPGBc0#*oag3(=p&zpC~9v-q~Ko4RN+7zrX&MWvO!*^DNTY*c`FBKEi-)=tV;W@1w;W)wiZ=*`XqQjz$2DVx~Jpiyi
z$a+ZQq21EVkO+1L&*-)mNxoXfSUJ+fGZ4_FX~0)CS{Hpz$`*dU
zdU?hz{j1T2hcTDLtOC>z*+>d+K~NC;ug%f=n?XVi%)NHmC_XlMTb&OqVv?o8<{o%`
zx3AjOzlD=6H!Eu6dm%_?GjZQorAUBhVEXxnpKJMV%@RZmR*8VmwbI2h%R2Jg>6zxf
zmDxg^r)d!3>9+NbU`DK4!?f)h4RC3ixivW;D!3``YIEdv$KQ`O(YiPiW=6$Ni49LM
zC-%Wbtma#)UTJQs(oI``4(N|K?}rQb6>Ck{OD6DjMB-5s*eJ)yFEzrfjH>}q?p}k&
zM-Ej`(gTA!4zG>=pCBbH2B$>nSw(?-e+WyIj1_fC)mWP3)1AP(;$ksbv;>DoWk6|C
zE>+GkeVdOCUd(6h6HC-JfR4&8Pc1urpoV(
zV~FpFQOB^aEKdby^jRXA5jp~JN!X;!F!%>WnOy3|uunBZaEfWUcsDn=G|EjNOV+F4
zR#!!fz2_scdljmoxGX}%RGT#8v2dpeg=iq)?ZAb=PSSz-@40Qn6axPxaw6tw^rnD8
zIodf-5K^>@1dWx(#`0WL_bI?r*pMleHe`+;5j))lO>>7ItLq%wL39EjCxGe6is7C_
z7uTc(Dy$9Asb+!O)Cw-x@pdnxh_Zz{{#}qGH;1&z*n1{pc9CIEO(_eOJz>_7M@hh=
znKxoDSEEkUV}_X(Yjo6wHLk1hcU+L>iPunJSdWKp4-WnP;vPH}%h@o5AtTf*q2
z#)#7P_YYt%+@X&qcOw8qGk|P1*u?O%Cqn12qbt>7d6G|tpSyENh51v}#^i04`62uj
zhYw0(gg2!r@YhMD0>_~;#XU<XIUxD`I4Uzm{_%_*5b(2EL8vyBSNO=MNMG^mm$T&
zx;n#1^M^mqVCj3SCF3teT{>kmzdrOTVHl0-%AaOs{fQL^P`aTEfk^+$55f3Vk}Q2?fv+l@j_`E23f6iYq2Ae*Mj}P#v*x&^nd1QZFV`>=Hlmr?zm|
z&nmU*;C-HWn6jIA&{aM60MACVJ19x?3^i(D+}V1P-J%DGSn83bkY;P68l!QD(H^UH
z@#i&tY~FJ{7fesF-b`&o_g9Cy+
z;-+M_VAk9*Dh)`>YR@!&i{(6Ctx#|to&Q4`!QZNPVhchIt-u{<-{2!nEQF6#yT2azUO5Sg%o-mgO?+1t~U;krTwN6rsY*laFWWKQK
zNizj_;%QV3d?hxO&px9cvz4B8<`y+v$wXbmWJ0ycaeffHl=U|^u!3F>ds-ottUSJi
zGUNvJ@6q;82;dC`#O>TNr@AMogRfFpq5mFOsNz0y;?d$S*IFwZE^u-!mr;<_5voUj
zHEld@PF-`b*n0a|WMx4;pQEYLFvwEY51$8w=&vp~sfS@wgDv7D76iIJGjBo9wq|^l
zI+xrMKIrjH;UU~ZpTtxn8c4H+F@Gw&6%v
zn0G|!e6R`z2P?P3N!~%myhWJG6ywsYMbes+LY9R3MHo6y2VSzebA@k5^3XxGLLcq^
z4ew-4PUN&0XhV?)jo6MVxGeC}elj*UB}Y&@cdLN+2Kg7Vr)Py-E-=(3Oa=pAh%
zCWwSxcwZ#sBO>671WDZkZld3`?qd|du6j`%l+@>J3IPza$J84c=6gZuzf2ks{q>`oSTra$_PPH#U7Y&HQ
zm05zRJ#58akTt%3$D4cxCEgB#V&V^@pkVcIY1K4nb1YQ-*&8wD3_&85#ZPllKdMR;
zgSKIW8Ht6@882-RNDtz+f508`kpbpz%rvFQ>M+qhJyU~kT}T3$Nh+a!zg>I?TAC-
z!j@bwJL85DDBvpg>Zole8(Y1lE&ce&>A`yJXgfY4*fg%CW3=?BMNKRC-@SUZPCRY4
zTGVn83dH&(OXjP-a>BB9>YzxA(A@^C+$qm#sB9S5K7yKIM2AW!ZCVQ;%YyOnAb~d8
zZFi5Dc6#v=X#S`VIGI=6wAZf-(YAg_NB_5uFu&Avfgtfn2SY>;sr?uSbIy3*Tj}p}
zLU7gbi6osrThh=iyEL@BTJe^HBhbOuTIN^Qt(!w_lA~>!4k|wW%0BhJ&k)==)nxFBF!OztbW7M4i;kw
zhSnNu2_#1nXT*y-n5RhDg3MEyrwH;F7sejUdpe|O({|~4bR>2xWUPL^#T#R^P6)l5
zx|;qRCZ?vxfa9|5r=MRXL#!D{Wc%x~)P1h=5FRNJ&lm7MuxEUL>aLj~aBZ*AAu;Wb
zgoqfNmoOxcbH5zU8z!`0K9_+`AHiDP&O1Gsv3}e3hn}=Pb~`b$qw~MNriK9XH)J2H
zVLdxFlOwj;AK8?-Df|Sbgv4lr`*egupyczJ{S+QWkU|eGeh8mt9=n8s`909YYI1p$
zk8pN=QRNE^u@xEsT5-frZM|jd02~AHa`be{;G(cy!V$k;Vz@ubW#4N%fpeZ=0#%NmJ_sY%bafic`5o=K
zlR&1x5y%oi1gWZ8gHR)T+3G~n{`?^3u3_mS!G~-s#P%r(uwX6Ry0#I@CpO_p;FM-B
zL9mZ&s9m|4+)#m%2zZSNPE+`!wv}CY)SjEk1&AnLT-#feDSMbH`ziq|!xx1%2aC!F
zflMZ;?D06plLm)^btaWX>#6iGcf{&T0W^#vhyVcK5O@37Fk`W1w3kgdeR#pxyr3Y&{R;%XZB39Pm8Za$o+M0~?vkB@RYxP#Y
zTgx3FbRE6i+=HvAPt@3V07cIMLd|o(&mOFe
zd&2wH-kvq>)-KOGt<)Khs5eJc;mDVq*Un(xo>0ikD8ZL`4hrj(kQX(teW;xKfvN0m
z+Y6zL7e%+jp7?DOQb?Gs+iVN%$%Kt*=}UCPb=wPp%m?|`)Bv1w_;+ZIcIQ!i=ET|=oNXa!a|$;wa(sUS=c@P-l%N`|bO{3@`jJIOhCmJ-
zXri>4K(pbM=REmTj7Knh`5KmvDMwju|5(x1uobj#?8YmmrH#Z&75UQm76o_j=@t0A
z92jR1n)Y~FUSoE13fAw5zNS@wO0Wepxx1YQ8}3D@
zhH|UVMAMJe*e5$!RXyb_OheXCL?
z#5;!s>v&?LVOj!JNl3vHEeYZBbuBed{|I#{ql6?suol}eu9L&|RWoQni<=Nc$OAdU
z#8cQvV(eA}Yfn1ix8AB|w-<-wkrkoeG7AU~?w>jQGUxC~;^HL16(6eq_~gtJyUf>!wIYNt+oE&nx}l
z3xb4iAV^EKDW;X+6=5O3SY%5w>mO_EoRZQ=1kZ}7zlSzT>2~6MaEdSlG3W`w#xTNk
zTrH+!Yom6MBs$mAPqoWx@~5zMtH!A&L#pVen$2K2EwK9PYVmoft{G&*q_8s=7ED-c
z`7TO{^o#o7YYt4N?1jSU=oSP3Nx0@l9&{)W%MVB3KGCM`ILLFr{oDHJoC@fgQ1%_1
zLy_c1*AMGZ8e!Yy(c!*qGceYbpuYpA=^U}XeR5BaR$eh|i^1`(Kd)aff@Z=r{|mN`
zjof8_vD##=BDZL@w4$qO4(CZZ_GzI}YNOi)o~AN|O?je3-o0RrtIgQ(G*v>QBqjC;
zmIkWvly(3s9SI+x-*i^qHN@E|n3PTG=w-_ZwkXPEJWHk-gX^5OAfIrdj-Hw^>E58s
z6z_~sRL#qCc7-r}6wPCHoqYwHM2ZdD*dzh`89FnFt5wZt8qi*D5aOS}@aQfnO|lNg
zJvxUVVvq1eco+jdNTUy@uuTv>EhOv=`IaL_1yy+FDHhqa6#0xH5p_d(B|bwtG>VVvT0
zF5%R%rP{_RCOqY>wExc!*hpqgjhn(iy6*h=$A#p-}(asF`Q{F&3i)(c=`FQtqf`->Cz4HoV
z#gB((37Z-G4>q%Jh?>^Kks%~Pk#@Xxqqj|6R&&dC#YPVlSAszkK4W=(?daYKHh+v_
z-hUvE{&JC0u9ajK{me4u$w_;CnE)qPI>~%6&k0jKXc1!nNsOa!_io&V?S{OPr8e4q
zn@$U$!xP~rwlDd+WJfvV!dP7BsW^8q*4yZ>P%)Cqs$9GH#|TT+jBVuj0>L{LqYxZ@
zZ4`+IOJy%E5V7{&ClabM!y5lu~XDQPJ=C1K~M5t!TB
zLRLZFUP?h<0sK?*t_0Qf01Z{fdN)770;{4JIq6_lj!mgW(9rA5I>m=;q9j8Z(5=7OSevBn9al8j4FIa(rlUlQc!TAXILi3D36Gin?($i9G;WmOL#z
z&}6r84^oLV$;pg#RFageXn~>3Y(7vzNs}4#RCI2Cs4!7=X<^QXr#;*#O^LZ^CFL)3
zSR~t1K~X|&E6W>`RvS^Z%AY*cDOI!P==E+3h2uFhK7!jSZE`XA>lfF
zhZ~=Gu;9x0#o)?a0|GQL1%ZzEjYC3ht5MFj(bxzQ9P`fv?Q57e<#>SG8EjkTNcB#g
zl-tT&=SGq?_P`M37O4i$q4i05ymVpSNASw0m3n=jdDuP_7wsp6++C{6mqg3;oGf
zFB@O`5=OlY$7vHoI3xfP;de}*iqjRz@E~%yYf{j3!GoOHf!=bg00yH`YNTZIK5obb
z{Q+m&R_|u(NbjP$`6%q};_+Y}g#r!Ro~gILSZtsuDmNu&B_NM7E$6j3IQM9RnWW=OG!-4fB=zazJzybSayrS4AV_l{Azf;^-95#S
z&dJz}wt5X+i_r=9W82-&&Lo}z6c`1KLwkEJyOaW
zO`DFiiuKkXdmEs7uUQMDJw0!|b>D^50~`%tq8Or3NP2B_Vi&z?;$RQbvPp97BJKdU
z&cWIi9kM+EH2w&4xii&~5CMUfRli2yis8T}rp>m`8nPk8>szuC)sm3?%z5A)+=*w)
zY)AKswGotcL4-?x5FmZ0UWn5iQ=G?sLLkH|ZGDHRNd>4LferqE=3-HMK4%eek9;8)
zvqV$E4m`H23nI!NaXTA1MCvroVYb7KukeC0w>5rFwU=FL>21)rncb9hxoITGiJN)y
zE!cAq;w7WAA3a{Z?%9c@!@MJTWyBi%+xCKmRufCC%W|+iHZ-xE`Un_h!@08->L%KD
z9({H@cn1XD31sdoWjmIQ=T=a~5%47vr7npDf0ST{(eL?6jNopZ{5cfW*=&e`@NPdU
z+QW9&?k5#(UhkTs;7iV7x3B*|764m6^<&LA-e3lElhyd`?Z0MYH4o37gtnSs9p5Nmw$_*jWiGtsS`#s~Xu<-+#6~
z$=1-k>CrWiA&oZ=MESxvj@2wpyXU)y*FA-VNu>Nk4O!1Noqqf+2TcTxe=8C~6e-(2
z9te<7AJMTb3p2RM`J}u3OFoC`|N@2*iYpnBVJ2&m?o1#7nwNYwr${}IDu(KYI3$zYApzis-oO{
z@8RsOP6CPPcc^9>TOn&Q+rrh;6fEw0FZA^xEXhHA
z)%s*;ASki6Ya{xY0-X}aJ)=(9vbhn{XO5^I^ZhmckmaIjy{j56D>EBHBO%-L232B!
z!(;twf#L~@VTY&mTI)guEP+QMObp=l23ObJxg%}J`TW8?X}M?8f5k+|;_;(&Iqdr6
zXL`-KWU?$%r``AWEpeWpIlee<{nF;i;~x|E#eNZCGvWD^Gy77ey${3w!_fBRi;){R
z@iwyh%9f1{6p0bnu9d0KtE(62U4k}n^fJ-9R~lkKX|-;ELvzo6robKn4^BGiR1Zp&$yuEW;gFB0UtCg
zwTj2vzO-Dv^UH-;qj3%N2QYxYuE_{*hr{W`Tf2>|5fZ{w3g5j%!8t;BLf78vx0?xx
zOxH0a>wU*9`W!1zXZ~OXhAmRb0@8!?+tWg2mdtACr$xJ|j=h}@ulBQ&Y
z?q|qz?V?J{mh#!wlS3Zu2`+v*z2V1AM{UZ<@4!g{bh6AYt*6rs%|#bY0ua({AltHqkBGMWGzKiK4Fnut!P^`YL3&?
z+G&G`2dDE-nzJqC!l0V=;%sN{vM3$<4o&FG;`i_Eoz7FKmwG=shoyT^+U(;!4%+O)
zJ#(-5-V#8on}0;lP5~HiKMuTOT?}-Rw>M5sB*}OJL|^YRx}lL(kuCr{3lcQxtiq2{
zZe{bp1|NEFP|C9Ms1{Pu)EK|EIE!_g={7|>!Pm#J=Gr|^0kfe*%QN1uE^_#Lt*m6@
zd!=sEQ)<(zI*^A6o7LQ7|9AC>7vdrlZe;J6IxygukibpKZxG0@YC#^;)R}?F7m}=$646TwpF(NG<)vEVVC2g3sagy+hlznjVJ^3?O
zY+C@624~={f+Gt>fHXm=RUq??9+LnECX&`{MNj9*zPLkaE(>#re4=+cqfG#EKJ1N(
zE?Ho?h4Aa6+NnwjZd@>7y|dgHe){f+=vU*butXr#B)XzU
zQFxratoTJpaQcG~k%W68z`}aWi|;le49YWyZ|dd8r*G`lF(s0`Dx`KrzLZF1iltN_
zC=ARLq}_|LBE}F_cI;txqz`^X`0z*kK#773iAvVI)PbOO%oKgF5q;qL>d@yqZYzLa
z8G1ySzsY(*?Fg-c5_VZzk)C=tZ;&s1)%4N4es%0htrRRUDn+a+PN*eob~7&a%Tr+_
zD97gDXZQny6d|-&x2jUfa0@qvV)C}3g`XE$)>jyDNuLImCG9inVSYyR!fZOGp4)9I
zvGD#jG3li~BQTQ%8D|!3v#b^^omK-tFjeK$7p|tnXBj-k`J=`9
zQ@IMFlogIQLzffD59ooQwnsCnNG)E*dqq>V$jl!wP&Q?S!yZxU_yj*b1uI<$1x`
z8ex9<#k4Dg4Tra@{(>H{i^L58<|XNQ!gwv58EfqBRekxh+_&sT=@oF?-{MB{0c{(6
zePi>2``icr0`h^*WcvSb^^Vb*L|eCTY}>YN+qP}nPm+#p+qP{R9ou#~>7Z}Ud%y3F
z@t%J*>R(mO+H23f)|`{)qlLTt$N|nIVul;BevnBR1Y=)%T_GWa;*k@7LibwjvF-}W
z#MK}kSI%`8vbO^Kp5_twwsv6x*TC`bs_vli76gY261=wsYBvhJJ#oD-0EF$vV%5N^
z#?zapkQ!umt066WY}~U|th-EUd7$>5t#VPf-WtE0(Dr$_oUk@`e-Aq7%lJB&qZ9Wx
z%sS+t&61f_m%Q?9n>f*oI4>r?UXAL?@9bz@!XS9$b*yT9!XQ+WR#Z|al^PEhFpifF
z6)g)Ah^_=UH)8B_5f-B)fLL!=iOJNm$kHKYW^<&Bc~N>JVOahEu;B9GCoJ}L{joaW
z*M*sxdPD;jc#9DX*aC2R;-Y@ILI=3-puW|BN0sFHJJD;HWFunFk6AprT=-feA+{xe
zr2`HOFVLR}HGE$PFH~DAX2b0bam>Z0a=7q(%=j2JJUR1ZADRmUFh3}IFT^d={N+b7
z#i+eBv%GX|OY=a0?!ZxbR2JwV%J5udYK(L`h|C2Hz%T)(8z-?EkY13J6psLTc;Nz9
z7`Ar82%SscH+CYO3+ir!dsPW}dc)m3>p!wdjDjBujWq%D8Bx(A
zjT6rYKp9nYL4O^x!A00oGaTj`R&(mRrK650qtiqb(-ac*$JIl@RJ>IQ&x|bJyGbd3
z<_Z_K>*K*TKgjXH;=M_dm?6Q(x^o!kmVh|C!-n9!l|LV}Jj@rGs)R4qFC|Lx6*SD%
z!NK?Tqy}3&mg!R2?IHkT2lj3k@$2otxA>0%D~7cNhj+_%n*s*Da0D!cP@krp(inAN
z-EPyk%h%qWx%a0SRFh5S8;t!ZKB$xJ5yu={l+zNI0ld?@J?}QFpK&%0l;`^3wFiZF
z?)ZQEF1cx(&mpV4d4vgRtV|3rc6bCfi+KK3W`$Li#k((4R!w5-=ecXV88bzlMBNXnF5Uve_Z9^qbNGcAap7(Ge#}Q9*98B(y%bS^(4_u%H=ERo|V(|T%i)TI1
zSQ_swiT5uFEx*Tmqs@bKJbb@b>PCLW&5;!20
z3qE@gxkP7z&l`z`YNDP+05WYDe#cb^oM--3jDJ@JJleSd
zleGGGfj3EWCf!P8w=eNqL9Vk|b&oH78x4KTu!OIsaU;RJ`1PUo?VqLdUSPES+Q+|l
zcLh(?`zZ6qsXpDhINskihkUE2X9}E0m2?mV>(iAv>e~x*bLlbnz;Lm&Nvq`sfC$4Tago$5mk8e@QXE<>HAZG^^m3+Nk6h!IPA)v}*$26~{$-=+
zRz4WQHPffK9m#X%4*E=pX*ryac7@qs&HmJ3Ox(_P5Vl8R7R;UgT
z-J1%c1^=Y5gcA?=q=}bLia$;e@XZNNaM;%cHuEIAZDidv2i=cT-a+)tA>PNG+Xmq}
zxQ~n=c5)J#Kpp2~&U>E#tv_P8gR}UYfr7Js&!y8Q2KC|#3&b~wTt`O{iav1CdwZ<-
zJ0a#i*zf~irLa3u@_>T0>`Ls$+Y9wm7jS@o{+#Bm)Z>KlhPNtpbh%sEe
ziCzHuGw0yD@(dSXEbM_eNDvuSP!!=?Mj`N4@{M?dFBl=EWzXCygRT!K0aO#Y2$OAs}W(ha@@MB)O=$9UEZJ<)+di
z{$;(uTs`_t6l;8N>LQM~v>$Vo^0xq9<*syEw-)O62K;!7MdaBJI`n*-ye!lw52H;}nx11?_BD^<RI96eFwv381WJV<5N8`aOjLRXic48_w`t49
z$(?urV#cT3k*P{F^fJn*n-AU~TC`CVMFzv0f3|el$YyPhk~ryNp9NBPxcgqCm}x$`
z(n^+yWxbUhxyt7piLvK_OV?p75UA!@<4??GE$65T=7>kS@H1iCxnjFV;4B$lyGGY6
zMSFmF!a1MGqBb5oLQ}*p^;%W5u-oiI4S@onItSX{Sp#v*Ie@R)-#Y4tik_meuZ%FF
z;CUa7d79*d865bEGbGbE6Lu_)HW`HCj#|MNi=h`cxD0IISUq{V{G<1Kkfm
zmh>tR_bQ;MG2=xNtIZ@uqk(*jQ9xR%nWtcmb?ljC8x@2Fk@mOq$dGxr5SYSElbG!)}@l^0(l)+b<6C95D2zCQ0*%Fg5We_?10yIlALig
z0?-aGesB
zm}#KSX>=qar0N#nIm9;Cbpq1deSuqxxRFoMoBn|NR4U}V_L+-kJ=gzyr?W#TKee9
zjW>mSYs12GYoK4{NYjr=;G;OkGYvf(f^Oq_ZhOOZZrk^Cu6}P10OS>R!$y&?oH$m@
zrqNiYnz7bUX9^xqc`qg^ESgA+p0gPc5KXMvzFp_-aR_6bpPdGv1)X>IdwLn{=FjGJ
zC>L4B*WDCOHLhhs(6eJ9vvJU6l3TT>M)=rCyN~mpE=-l%Y3*1(&Z|ANVlG56W-^eb
z?#UYVH&p82u_*rJIAOP*2KKz>KorX+Hc-m8#Yet|VZgS49sP?<=(K#$WJ=IF7lN+F
z036;!D*+rk&|C_r;@D~6O@j1~C;Elt|4P1JBIoi-c}RmGJZFcNY0M
zyA!0F0b4bR1Y$uthrqAYK9bjZfk?cZZge7$wF%`9t1NB
zE|R{T9*d%?4Xri#DDD3Bf6%x3ztJa4-9sP#(O2MPJtEObnX=YF@4MZ&#fM}c=4D`C
z=PuSj-C>q7hgl`rGcF%K9jEPx4^6wy1-SxvYs3O$1DQ{&+H@Pfl_JRT0=oze{H59~
zp47MTvR!u{+$?3!2*cUQC<90=qBJwoSowqgAM};3PXD0K{|9}sEc|dj!~73)ji$8G
zb%sK}S18Qv#eZB}Rr?&pozC0X(csUqIE{=XhNFTcwb&cNw8P#Dy|I~u;S*fU0ll;(
zO-#H~ZegG5KSM!p{Wzizmu*U@zyHv*PH_xxlPlciyMuRPlsA*#b(ll%&GYM)UuKc&
zdSq9~z^>#dB*Sw)OBBG5l3Ga~^Bl*Tj
zXYKJx8pCh~I+d-Q>lop%CjOQk0ic6s9#S^MM_~37J)oNIC481w(&nzi%8gDH);Z5b
zxMAP0;#Ov|RRK(8ZoY(6vi*-6VIT2MNgr**;w)Q)FC7Tk36xPg(2E?76u5RrMLN2$
zPRp9gzG1J%2>&M*W{f5STSRe*zc-kfs8{
zZm&{ss^SF{637uGv_xcrULs(Rmu%iXEdafqPD+K-b((6hc
zzh9jnwLvodkrH^~SHriR>b=kl;D&GtzB5LQF2zjhh7Ieny+=q2dCx*hvuX=26Mppx
zyDUrOuWs>99bs1wZh~c3B_Dy^laiI+e$M&Gwy*FrbeRZt6h1o)e?Pt9M;C*s7O*Kd9_BHLp}zknJXm9{iZv+%DD+#z)C3LvyE|u
z2rA}FD?2@24NFR;|5<_mndQe^$5%C+g{X|+Hk23IJMu5~x!qd?e?|+fPgfL(Ge){_
zK$H7=>ekVqlxBlL2hOaLxtuha6EEeam%bZ=;M4G
zuCU*C!6X(*y5koR5rtxpc0d0796mLCjj0WOmbbkB4=T_=|B
zBGgwvTD8&(^ecW7%G(El*={sYeCxqK_W?5_8am{_ko
zYQCF0ua18OIPrNxn=Jx$v36#E&3Vp!&2^sbeoPw*euM3st93i$F;;jXm!o6BP;@az
zvcedsOnUveMOApA*SjCN=cpn}0#r=S)O&(pX-qn>@^Qr9Dvr6xW0z?x5~37$GHniX
zrK+)p>^=|g3@6X(O6Drr9>
zc0~1rf$S_0VONFBb*}E629kLKS=2gm>8dy~541Lm%Z2poUM~
z+cB`-1G8;mw~j5)g#KtEKcRLM!09qB|uttAd?xQXa;zSbyd-)BvrK!v4#b7pPlKj=J`uAAC^v}kt
zaKvl1$=fQ}XUGCDCHy}@8
zoCAE9+g^ll6mvyI_EGOyJfSMP&B{Jx(0_^;KOTvnzT%x3AX5H?qz_$FuSnqbNcg3&
zukDjx5)b!xQFvl_2`iTO~2j9BjgJ6Z8
zFNtwfWSOF64uZfwSoa(nzHtf22bT*cQg}owy5nj`aW`JPx4W$u^3}(YHo{34*u)pq
z?qD4wPYP}yFbR>jIkFs?cmFl>C&dBs7~KbfUo9AMaa3T4+5>X=+H~72zhFpU6!MyN
z+dTh>_Z2+A!thY@@N=whjPM%wbFy#L^|(HC)GtC63)Ylk$QjSa3v!vDtoq&C?Gyh0
z{r3O!*YCFtCocU|hs7U{BKH4VA=1C+fZ6{4RK9hyYOz}dZ3Z{z=ICzRviBmvLB@bZM~{`CPN%71pmq5daKN8mfiHZyfN
zBuX0nF8yvEm;$m{pBK-V%Qzix0az8HcWA96?kL@T0oWV(A^mOvSOB;!ona9;1GpxA
zd=XfUPuXS-=;}P-OX|DWkkO#%&otXRN^ZpBhm_Agu$GSzYNMnTEd_xnbsK-t0mC7i
z^n`Q~)y|dD7KigbL%QbD&%&AD5Wma#tza|i6g=kamY}dlI_Gdm_5nROoLLAD7Rbzj6FevlLXAtpNN@{iBpknq2}d0j#o&q7
zXzA3aabW$;=QS_8TB{DaV9#B6;D@lEeY!3<&zddUF`G!E?=QTw`)E7!TcY2C1>Lj1
ztk>AXFID)`4VsdyO67!GjBUkatX{d+F4d{+u}GLIRX==OIhA?0pESzw1wMz?n
zn?GI5m_L@L3$Fm90x&{px8O?MyvMiM-PfKkyO1H`H0RA37HO1U>6drdK*K%HTN3%2
zja~Nu^j2*>N8AS}!}r)QzgeuM_F(9IR}YGO<9}It+rw+V`sC9wH!=mxs+OWOtY2hHcG&kB!U<
z56)^9AL3Ug{8sfZP)&9s5tQm90=7sd*bTNw9Q*>ggp)!lpXjTJ2y{x(B#}dZKWjyz
zT{*gK(R9Vc{u!ISGZxsC(C+R{O)UxJxIsjP6yMs@nMiS;t}X(~2Q6b*iTM4$9MBZ2
z8OzciR)IZfT3AKK6mlO{1qU((KCJ#hjJu|X+Kv6!CgEeR{}U!X={K+(@OS&(Z(vgp
z<_{Ksx&lJ|kRGYne{g9yjzw40UDFSi5vkqzOZQ;>{PRedgbz(jccMjWo%PvLd_n21
z8^BT~iYbnmBRAfl(pAC;{MQ6^4SW{sD8DyYa!bMehNIqsQtwH12OaIu0Z3=uzJY=p
zJl`gW4+!tH!t93oFk`_Pl}32sIC}jpkrx^PnEL60Zvv|UAe1mx{uWo#
zCj`plLMLUQ=+tJPP;?sq&zk7{sCd8e4c@nz`Sa-b`Tlou{x6H)h;e5OL3B7mo)n(V
zd+&3dd)$AveE}a=XNEw2fj)3&4{=eR%*8^QOt`~%yQ=qnGGo&y|CB~0-?+jQoy5h_
zpda(u&pq|AYk)$=tO|BL$O(
z;lZuJIkAfZ)V)xf;f}DEE3aCchV7jVIq|nV@u!y^8S2YJjJZ?6oacCWoDO_MWLZ(sbCJL*BrF7wSap>%rXFmJ8m_~*Xz6%GJlf$%6
zvW+j#CmSnA!mM55ajesHtPh@FCt9wKGq+E>%-M3o>d*X!w{_U<6l^)RDcJmsFDk=q
zuVEwY=xWWe=ghk@CvQF@ohx60`RIqwuBz*PTzdMYLje(lm(M&vKtdjLq4=xCENe{8MnR^$$Rzc4Uq^aU%N$ah%+cwc9{B+{BmIU3d
z_Kev*BdqBhsWPk3x5dxki-!6;J
zbRr_7e1NUYCi{}qSjQ09rLjmq?p^=cyHDNI!8BMhiL0Te<4G15rAr2T)_ptNvis~@
zK9Nnc-{`k8_7@Fp916Fl54SYI!^BF=n1Y)Rv~Fx3)c1qNsBcsR%diBzur<%UI{U-*U90>q-1dSF8hEOjFIL%PB-T}GvhHbZ}J4Mp2KA$|oBtKf|Z
z!CHzkM_^qbA@+t(e3UkL?)Ck-SHANHCw8C|I<^Yr&)FKLRUP(f4PEni_^SrE4>+Qf
zX*Y*_{O$=3pb>`lpBW(^YaE#Bn69c|4!YBVN6ZK%)W+{;!BvcWit&#Y%!n4u3~!$>
zgpGQ~OJ~9!$$=TO9{B~E@yfI_?O1%~_`i!QEpKzp_fK&({qgYn|DtbxP7QI=iTHqF
z+T(VCAwa?Y!Wh;G
zpmP!*Xe7w3P{vTWqFqr8k|(_k_8lj@P#wwdIT$7)NXZ+bS#}4>v6=Pa;t`3x%v|s=
z$Dpy3rN+nm2@xMW%*>umX#fH55Bv|?m@C$q6akuWnq)Il8Riimv}K%ZV@w(BIZUp7Ia)!OX-V2UdfX7aHGcW_Xw6eo3Ij63FMXgh1sW&7qLSkGD`jSlfk-Hp1(S!>ODCumm~
zmyEq|)s7#avC_Bl-oOOKKfc*T0dr)8$m7>bS+M}TV>c-WmI{*
zU961;nY=;!I_dnt}pn+jiHsc++jx>8Wt|R&PIAR
zT||nqf4r@C-K(}=I4hAZ^YU0In>FC&b;c@{b#GZzWBKMIe;kp9AtspIqJPMe0m3k|
z)Kw9oi!9uHMP_biaflQ_EJIeK|E&go(rpJ^WM$;%%FU$S0nD(_s}PGgZPn~M__FPq
z{xW7agVmgxn0Q^!6uh9jlvZPB_iy?67_|svuRR?Fo;Y!-l8kX2)i4PiZFgdw1SHBw
z@79;Bz0dZU9RNJ0RE(zFG>WCnoi+sB3D*W=E-7)eaMU%m4-2w;dD#qclKtY=Z
zG9G+TRI`oi`21qwdeK0)r2IaqcaDxtVu`2kwxS~rhNE3b-w#>B`yorimG8__;eLWU
zU^U&kIWC7kT>NNRv`
zN-y=y<5C_s0y?qfMPnER-bPP#H!>PHQ{8%Dvjwez9%SCRztmD6?Uu)M^kueY0yt-?p|@XUk^Q=H(;*
z&+bf5rX0rS`-j!famg+JpX)z4u8w}6)nAB6i+JWq$rO(ZaBRaR*bK8!))E#AlYBB7
z07>4;i1A~T2Qcl73YWrUhzGLwjG9L@O8r6c3%*rp?Q50Jb?Ht$lIUf%yxWq(Q_0GL
zEaF)?YYT2~j`_qz=B1g`({(+Qyt`xY9wh-xY1iPX=;cm3B*ueBJry%=4n{Ta%Bg8J
zgSc0GEW!sPzlz30i38g}h8Ib^r_a3#sM4|XjYMRuumq6Fr?
z24%Z*cQSvEa8~S4ujUDY_S2+7KU=N>k3_~6*$0RS!}&3ir}@3bZql4?ZcnTtK+%_J
zh%0Swq7*HUsJNN+oJC+9+BBC|E{AgVeMzt2@lVdm7&(pMIT>R5#IZPy;Wb&kT)>{R
zzy+hT3T67SN|p8Qv|68DM&FP$@psU@_b5?cQhm~nCfB=7pTxC)EuG%kG2u{{717cQ
z%M)oTAV>J@!GjXV>R#eIQtqD`;56VgWY@vvarVxpCBFLql7i;Ag
z&A%k-dg7MZ>h3k)m#)BmRm2cJp9Jc1y+5JPLZ$;ZKMGiaeneH-&%%WMVS&_*^Sc&+
z<(lv2rs!*CjZH7R14;SN(d*x>!v?kw;b}~r+dpmRz-14sxZBw~wYsvu0JB|+j4xg7
z@7*G$@Wh@^V?6DO`ST@zb#;IFSiz%eiuGp+^^Xb}Aow}ND>_wTIFvCJ-%n&b2na
zOMopKeL8z^5AMYQXex0I08SZEhQ4QgfO67d{mZBm>95?KG&ij`9d$2I`Ux>!v|qQw
zV!hE*Wv4YXIO}Y!?5gVYG!68BFASvEUWe28*(*5?9NB_eQM6#fb@~^oJ2+xSn1vP<
zaXMU$h#802xH4(sxaV!Y;69%w#2#M)2hvwKyn3cMSiM{cAOaaz0Rs1M>G+*5aF%6Z
zP;*BYf|rqs?4;ev%_f-5&tbfKN>}rYpsvuNRbj7lQXqe^`%LH`Aar7)QJOpV*(M5G
zWb9ccaklKB9AsL%FxuP|1`h-RVLo4=Nu!$yZ9bztByhFa@*YTXv@K(J`Q3HGP{5GyL4)-AGiLn@!&@fJT84c)C$mrDpiZdaaSI;TrJYyVikoGyFmwx@?7teiyU!nWPYSKhI
z%xNS-5Nr>L089hV8Hr(7`D^)!fztlo(AhM-;+#SE9!fz|cg{h7xm@O_L&hOGZ_l9{
zk!p3eRzUD0e2K{rwU1X5pbYTcW?Fp~{$te$o$c})#T*w`)pg0FwyXZ77<01DfE9nd
z89fvC!rimR(HWBhqHM@C-Cf)K81s>~!}bbx0@+5yO8
z$CecgZT2mTAV{rH!rw!bQ#o$VV4#lje414;8yf%RW7LdCRea9(7wjW;2AC?-g8&jfC4eMDC3Je2ijZo53E@$c4@%Vb%|S`XP%2cni-VC4`tl+W#{1wR&D
z4l^jBIpAw_^ZhFwX-Wh4cV@7=$v-Vx6J3khhMRm+LRrW;^}R~kVD~yB{Z+=_WaT=K
zLQUSj6{>ARX{0_|bXUzLHF&mCTl;q~Y*(`UNrp{DaB`SvT<0(PeF^2Fh9}TIMCzII
zXNcI8_}VslJ>zQUwYLoQ`p0U+k!-tz?bdF%JAk@HkH3u)f=Q?0ZoOme%K@<-%L3N7
z>~s(wjE+`%YF>f^GX*Px+IGs&kbS`
z76Hbw2us5>d({vAJ(9&A=6|J;50riA!iSY4JrVqC9}ITO9|K|$?;Y9t2!TF<1fja0
z4=raB6~phto2jzR-e2A
zAr(1r9ovLLYE_=?UVKHP!%KWLv!*zLa{$GP&yq38H|p5@GSUf>-t;>h!QpwEPhaJ!
z`;3|8n&1E(N-~vq?lV7pH&H(fX5vaOG|OGj0m7_@@6|J#}aO$r)gH)Gzyl0vJ&9NqI0RwmjF41q8?l
zE}u*Mg>G`n$)I&Y|NSQV4XGCrSKzVsM%tx$0&%Z&C&r~+UC*v~fFR7%r
z0FGY5w-8J&dE!EqrTMxL&z|p|3itxP>(yAJ{s%le;
zU2L9cgOUqVEnJu=RcBU`q@vXn67-;=Y{CsAR$)QbDx%a9gGwv|uK{d%q3Ae7foGGYp`1wB&LkN5vB+L6
zTM9lEv^^--$FCIzUJ+-Z8vwgZg
zA}-!N;um#w3-OnYpXYww@79?E>Q>qGa^cK6s0f|F7PnYm
z+g}fHnL295=Qas^u`Rwm^uRlo;J)4W?g4gqo1&B%X&>-NY2N(yeF#U+ja=A_((N$D
zk_Gnshpx)%>guB_fWDYZt7K9kLO*0xqm&zdAoX;IlYl6NWCbNq^;43+_zTwWt2yu7!28-|&9>O}#20o$y!
zibrfj1Lq+2DgsooZ>0o3@ZXR{t9clW0_)XGojP^0#)E8RfJZY6OehqrG>}Q-G)T%E
zL8xu$c(C*~q+WRCB2cksA)-UjQUZWAJ_%>An2@KZScrT^STOI&^p&hq1Nuv>CXJKY
z9l~UOSnA^G&)Et+`>qU`7lGk=!zijv*t{pkp&XiyWf2pKIIJ%th4T$>sm%8^mes?X
z*ev$I4p8V7z}D`FBKapY0aoBQnICQ)3k14c;tg~YAI>fucGDptWuXOEZsDncr|`09
za_z*PTelznH-=(0B?b%S`XW{#$A)fIYIS^~o<3KCrVNvgu4bo5+~m2z6$&y_`x%bf
z`X#iO!p=;|)()_jS<}#1l~t8(EGZ4(6W+u9T%(f^@W&^3ziAgw8*nzmK40)9RXwF8
zk6n&tHPgYctl2@fWcl1Fkw0Y1F)Vx3|7J`CPK|iyrJWcITK>%Sz-`e|N+_20cKs+bZeW_iiPx`oy8WeGql&
ztXifJpsxH(8}I&cgC7TDMS_m3OhNrP6qHCZk1x@`bLrS{>Rij}v;7eB&+Uk!D>Ea&
zVde{@|7W3(kz8cF(9GB~p20ly#N8nX?FJRxmM+@!RIcOW7VGysY^S~LhC14DW8C~;
zVvSc}B5~=;@Kn{|tn7yC;2#5k78leO!s!SDjAPhPle(-KeFmH6haLqg2Si&ISLHA2
zYWPz~Vuw#Q<7Wp>-0%y8<*9c{ZVKgMnzLS2+Gsh)3%I-xsWYbShfaI=*}#qpSqR#~
z!-{baXrPy+G@UafI&VqMbuuJOJ>+6$#ZzKm*_axzR;H+;(-xt&$6(&Ev!>>k_{_lo
z>Qv*Z_??xBzg1D$mn&C9YTx!CY*@uyGp}`vCZ%FV#-wISu!^^=1i9gUGV6l@@Pn$0
zj(>lH6K0{5HG(1opic_;{eceig{#lybYv|Td3bPPxWaqf2;7(6!(dJ`g2mJusH=kI
zmC@~*)QEm+Bxgb8#8FCV4EP($8=WQ~V@w$I2s+{k_3J_;CwAKYJH=dC?f7MSWP}!o
z)V970&zJ_N3%WD(!zxLnS{zb{Ut38rXecVH;Eg{e>U{;2t(E#Dz=fR~pMCDtLqz3Yj^y&xZP0_){ga9|&q$
z^jUZMC+Z4ZPOZ((a)rx!?3e+7o40Z=pxs6_-p<+=Jdm$Jz_(<;9hrKjo_
zflWl^Jor2b-Xxlr8N{bE9-lSAh#^cR?%-b^AF#_0{Ljw@;$0@ykcx7Ep^K4{+0Pq6Ry66z=PyO$8Cf
z3eypn0Ais*pc3N{qe1Xmza6TPj9MV|7%)4ykY5(uzT`zC*|jA_(?122SIFg~=a5$K
zv{r8YI5xb$b0J@M8?WU6$v=YD9XZ#Gpe^@V#2=F3*77Dl>ai_>7U)!DbeiD^CXw&T
ziVt<|a~9Hv24XpR<`iuStG|e3?k%hA{MYAn2^j4%n)w3{q?}zc>(p&Pju8Pph
zo*tcYkgcjLwX86Ys8h7)*hILxu3Cl2*98wbCd*QNH)KN$+!=lV9vQdNM41UL6nN3|
zZetzG#6$$k_tpY%v0&^E$?Egi;X_0w*{RZKBVo
z4myal?27%v3!`6Q%}I$LNHvLE5q@v_j0+paHjO^|KA$RWA(byctges-%iB2W62fxXOt7F=W+~1uIu8M
zuFU$A={nj3hQE^IbmLEl!&HLY=9P|#iB)SxF*2zXsqU~$&J
zp+G-_;rE~b*~`@>W*U_dCNWg6BgwN(A4F|$NH>2vGWSd3L7S|rNIR`JNIpUF!>}CuX^3Z
zreYs+oc6ec&I<7a`m-6P9O`ErbCdoa^2&3|8uA?NqnE!j8e?vzhf9M6GP%Z*&}m}5$O9K
zuU|K8>l#mY4SPTgk>0U|SY1%aMSYPqr^S>mHmBV-d
zu4vx3jTzi?6ZB=94DxDQEZMKBKWRzeE($!f*HS7RWfW<#_If)@RBgaeA7M0~Qv#A=rC0$X@7pGz;__ot$Rh>In)^@uZ>Rj)$
zB|zq{?J+24k`56th^Kl-E39V+oMaJzp?@xNHKQx$O{|o;bp?^npdB8Re`y<6!@p^s
z4W2cN{}l8?_~ZVyUCfX9?iwXM2tDoBYgQejMNRR;nXJgMLM|;dak=-JI|DIgi;q7#
zs{L`7)~PPnu0DE~6PU))pR)Y=uZcndyd}ndFd(2>7$6{;^b&5c|7mkTq~ldV!2x2`
z{dJc$(EgP^vx6-JSICKoYv;{fgx#&-9AEWohsoC_qkEy!c&+Sd^dnESuebRC|u
z?fd*u#ym+p?t7uYx$C4V-kD&CnScvXRAH(N&=&G{RS{BlWVWYRb4S@vCaAWYH#8m<
z*U)ljq3+LOhLAIb?p>x^`rueaR9*3f)Upa~e}0+!hX0+_BC~r1e(V
zqiXNF{LfqDsc-P*Ph$aoj%!9;I+17aI~?${QHvXJKKzhZzl2y{FR4SVMOPH%iun;$AT~(hVdH|XgC71CdQYo=b
znU>V4%U9MkuVC$IOi|3hn)7yE(45Rf#z>$bbvdhNC}B)=#=xd19?a4gwiZ(QUG2Kq
z^_#J4lnnc5Y#~JwTE#CfybZ@l(&Zc%@lNw30CEKjl$N&*PhPsZM*eybid5L(rM
zp2TeQz|48%YAbZB5`1M9D#196Da1$cvhy?_WnWpth}vw!p0~t~M$O9UFRFxfD)y%Z
z_y7rh$ymWjJw8Y~?XKKB-wuyQ1dVNScOxX4Wzpye7A6Cbh@juxpUFcO`wyo3#I|7H
z_M(ANevyS45CP<55*Gyz1jDere!bf1swFjlTZMn(DN2Y?R*D4)gzHp
z`^DT^#rrzPzz%Yr&$c-;iR@>&a15+MU6NFO-ZtQuyMx@c1jr!A6+~zJLH|M
z`-o=tS6gtlWDHo^^WZ3O&`#KGgi8H84x`8-V5>3U@LfX
zE_cN3-Fb6rAF1H?eCy&omSr71_X6r>vJrG$Th*PQ*Y#^2pT*EC3DzsY*NdXFJMS2z
zcG5gzTLaeR7egnuqKn$h^z3olJQ?Seblg!3Q97kdD8_M^o=fxF5_vj5{N`D38+#xI
zbju2gTbvP5f7SSa;%%Z@EV1wsUy=iyssjVbV!Xk@6muO1!1tLmu!Yt5
z9gh`Sop`g%OE^HIfjiT|lBBsUd;cPoJTU35(+cLOrZOi7&`1gB_1>&toto
zE&YH9ryd-1WP}?8n_U0wCcDn<_DHQF0720dl5wAuo69M&-YhW_8PKb;FA582cwL;<69I
zm?h7>cUE@5!!o^Wy&M#M>u(6E6!Nn5c3NQk7#e5y=aohlGMDB1w7J(0US;ja3uabx
zQrBYaXMd0OdVS|{M;dceH
zQnv43MfU15AQ$=lQGbIJm{%TxEMB9k*DA#S4^{6N99YnHYsVAYm?RV1wr!geYhp~Y
z<4kPZPA0Z(+qUg*p67h$y!BRf?dtzsclX`9*R__2K`4StjWWFjy*;^pMAPoa79Cu<
z-j^=n2Exje$8h~N(aG@%XxKXUc9nO*qLncwLltA-pCcFBh!O@?Nh9fsMRO_(z)9ju
z(#p@BJ$-o)+53v%UdJ%@PYQV0?|ac{$k$Fv&k%Noxhz?4aG5BA{EP5!r$ua%L`0F+
z^@t0G$2~6H;SdCOKhn_hLX|7#S=bT?Ic5y7UIRgHKve{Gyu9E6`WK9fFu_wEe{^ZJ
zz%uA+Herv&?69Yoatj4-JM1t|09^)p2E^3_5?oUZ)jFlW)tp%>j#Mcbi8x3nFqb%I
zoQNPd64_|IXn4!it<1;`o5ZD!=Dt3(GxKWDNui`k-NreI`%j^!d
z*O4p-AD4_Y&;br2CdNTj#Fx~+2RwN{me$5~?=pDotxUVLVL@G_qioTFA+gs{OH5}*
z`@*(T?83Gh(6QFh894oVn(*=>U5U|Ty*r%veW!P)$6{~retoSX%Bs_GR+#LO*z=&T
z+|C_xdBiqbkys>@28aiwx9{)V?f=Zgn((xoOfFiH=*R2$4f6&$L5^b`TeKh(X(MG{
zM{CW}ywMSO4(Q`ffTphgm{7O$XI>*h|O
z@#aZkX#1E9+B0+RuNK;_-Z70^wb?dp@~YTFZI2H5v@^&t1fb;|rc=q2L+a`f-{Dn?
zVXL?8=edf0*`W^KyQN3Z9lPI41Z#HU;iGP6fB?nB5klwOb{p?H9nItZE!MN^$%gGU
zUtYKuWRLgkI>W@q_s=|D!t2|B_n7N9vfP)yJ$!lpc$#-gK+Dr0_OM+4GwtKmC4eyA
zCECjpT!6Tv1AqehWU%h|Egxm_6LC16eUr7_6Il)4b9zE}e=qk*I6g~#7A3DfQy~e^
zO?@i>9aaME5JDCpspUJRTNvTM
z>|ZI<0jj#=mKP5FPr5gR&rFLaI);r&2KVQuyg>ozGl2D3LBDKAz^gRC4G*V5S6;a78VJvq_pGam!zZv*!8
zK}baY>}qONv0&UW)5Tz6^#bnW
zXz@x)6}xZ@cyfKq$rL{^m+AtV4>3dA4JK5_x4
zMmrF+C@;855k8{|P82-dUtNt7J<4)b@zx@;_6KwxMk!l2W1iW{ZQ0#v8aq2X+Y;TH
zrk=*a^6-{qCS$~GVRXBiWIacr1YRi
zkX|7fPiO;O>kux`JV^*M+{SVo*6^)+$r9YoO^*n-e2`xQ_O1i@{9KkOmG}5GNKP&>
zJjl&R4ax`-WqM)=F{sUW;lj_*y1)0*)W`sI5&N#mM(^Ot89L(R+P(o*P!8oB5HA+U
ztDMBBbKQ=mi!PC@#8||DgP_5!#HKWB8fGrq-DH7d(LCFg7Kx1Cu8{9Za&>7mwzo1-
z|3=Cnwf1Kry|LSsn&VHc)9R0%s!7kv8<-BI)i^Z^sm14p8Bc8^<_0?BAQP`r+E#?O
zHoJka?a9eUX{M%tIuQspNZ&-stIQe~QSB9`Q_}fh3IUZ{Tg+
zD-M)Rbu?y`p_=J)IKqm$Il&lV;gvRY9}+)+#{dnDt#8HB-=>A
z)f|%SD^7>m?9@rK6i_|)tEhIork!cp@Aa>O=r`Q&KWFjoi$=umlcWH#e0i1P050Fb
zyqZ5wyZkwtHv$84}>pokvH?WKjxxRp%DqRVGyHWZBX~(ygLcojf>C8$r(|WC5omZJuO_cY>tcN#+G!
zHUI?MR-#BdM^T5Cb>T^fZPEU6dL*-8CY-`HL+Vn`MD~!C!h*wURfi
zl(BD;RoZ$M=CxZjY1O8T9g-tewbMi5g`D&|Ri$vHAvbmut%X%dnZ2&c!rzKc7;a0A
zbfuUSYNFe(7$4IzI$_gZB6Ca?TQwmOq0JcB^fDDlIl!ef44c}jEJYZF>Bbb1m}yK^
z&nmsNv7Df2wbYgPn%l8KYX^}Ab45!DPxt`rcXFtQKK%s7sWj)8)Ey1%PQOpRj*s3p
z2BNB44trUdfgg*o$VFJ9+_;naL>iy>ZpO-8(FB+EVBs7^7Mtzk_{)J)Q6`(oV?Rz^
z(L@R#4WP;Ibh&QHax{^7%*)_Xm(bzi5Pu$@_v{MDJ%=`2yRn*Ag?^pBWbj;e%FgT}JO!oAP|+
z=ohzpLU7%-Diuaf4uro;L{$v
zY28>A{VBV2KJ#%Clsi$YBOe%bnLEhjFKj>MBar(hBi#)-66*+ait6zglABibSK58!u
zq9{_KPkzDG+k`N+r}HKarSggoAh>j^ek0Q+P!2(G5oHt(SCBq`FDgjWAg$srjKV$D
zQt_7YUfT!zZdY<7>muv?*$&c4G~uR7mH^xsgI1$^|6WpMD3y?XsLlEO?rdFhg>}uW
z@*((v{6UCwIu!gGTB?s?C6M^%jXHX$e+u@Pj#r;$VQS%*NQYe+$9%dsxZqZOB{;S+1{rT_#Uc-~fGt>4PU&NCqiL8FDl1^_
z8}A1j(S9W&q}%EbG9*9!2e^l^uUus(*uqZ|m3>6*57?jPGP{fB1IVHoaiN{w_6d{?
zJLf6_Q8s^eJ{K4Jt%_J!Mwdf^j~4<|&OF~h(gW;v>k|lT@;IN_HGBT*QjW~DLwz|L
zMLDZhUTuq;b3c*AEbh{Fh!6%_8@U3S`Sx1=f{XARLp5vgs{+4NA3949tV
zprH;7o*6jl+6
z{v2Ibc}N`>1bGAi{}JLGoM}f
ze_EqG6zX&2lClI=DYJ=APA0U@^#)fO6e)$$$q)t?ytr!1RJx3Glxd35u3O>_y)fok
z%rZL}DU{-Muqfk&D^Iq#Miz1X#pWEA#YKk}&46X6UN>`aNN~_{ptXfaeJ6B9m0EW|
zstfPM*wtwS9mhVOY-^rEbzJFmvF~pA48KQ51pA@-5e2-U%L3T=;-|J5_E53I+F0I?WYIPw^ON?sTLP3ub@%x
zbdV9X*{Mq4H?f$Sx1?7Qm_{yVp-N6W-N}(gUZ)w6BuD>9e{uWm;Ik1J*qXIl;jYVH
zgf{PUh(jony&h-H4-=81jTcqx_BxFp2?NZQkwQ{vrdf#FXv`-<0R{tjN=j0=PqiH~-bc=V$x)#t?(5si?7Y>SOu7^RZxEUb&cBEu-q<(i
z#0GK{OW~9)@)3WdXHx|tIkOFG%TAR>&>uTP=N_t>SwIF8OjDeshYUn$=S?e7Yvtv*
zgmJf}`DhwbZa@HY7Ebuh7{m!y4m72SX(@|k-jCpu^JtZRGgEf^h0{CSgK`twhn6ub
zhztAFN$!z{hmq-#+pUpGvfm`;qUXw%nHIv1CE|Q#nn1Dl2*WDie&g;Ty0Dib<-^wA6*efNkFjgqiKjI
z57n3uHSmGAe;p;-EhojN6M7GlMSz?@ZstrFB1BoG_o1k=
zf6u87Xb_Ln%1832I)i`EQ2CJSFu4`hH+3YNV)O80y>sszaVl^lS77%5Q;^+g`pL)@
zZ+)OA5hfVS8jOLpL#W?$!U
z1A2EX9SM^y0o|X-CTp_w%fa|1QKNqu6Px)j3*>J1t&8uoD<8iFL~{WHdud<6S6QgOU62_9R0zdpxN>+F_pj1IwVw4@?o~@>37^@h~u$FKGr@Q-0#Jy?&EO;Jfd|N7r8Kidp3!Q*5md%
ztx~%+VJ1eg2X;0PA)hRff%#1RkY;ylWSDC|L#$n4;f;hK)1LM3$)UdRkM~8;1L{Ut
zlfoQjE5hWx7U#u9eavMJ#=VEOm|O2?o6&|>NqDE=()5OJXGo{~lktVOGd$uGpC^d?
zI}!dp@%B4vhXRrl{lhh2>KSN#OaonGaNzlho2?LiBkq~OF{i&Ny|sN&A8lU%-ky$l
zOW^$HDxYLsMB!H7Gc3EX_ywEbAbXnSot$szYL+Qcj-h1dKJPJLW*2Mp=($Jp6R9Ke
zZx2=Uw9_sMFtkO{Z-6w2PJ~#%sOYT_
zml+Rl22Ls$<*RmBowBIT$<-CVCJk76c)t(}r`C0=?K={|6`BXo57Upj4p{!2lIRM$
zt*L5E=T*6gl~8$Q2ns4hl2P49aIVJ56oZFkGGu=
z`c6UJo4!(f!07`%)C<#X*zp!dg<{`k;t?L~Lm@rsa}#g&KYiPwK8{4FnU47aHYL9J
zaH}_q*Pm)8$+8n~0zGvVRH{S;A3QBrsJm-{L5l9v?~we)#9t3z2h3{t254I=S@w
z6dQ7WZ`RzM68p89VlTijA|Uw5Y0E84H}S1R&6Q0)$-b`R61suS{AJbKucQ6|#8z*c
z-to=<*C{37I7GD%wR%sJsI@eVyYPEZb_exf;;Yk&_3tj`?}cjzpjCU$5*hpy
zC+2jr6(M2LV_6i@S9g4-M5~*r^?c{FkM1|68};)m2b>!Va!#Z5<(S3_ZRtjCY`<2W
zd^?eW;x0OH5HR7-
zFd@Qj5LlrT30)86(|{;6fRqj2y+@z_C3yXWOtB@={~ogoExTn@q`?`kZ;tg5x^b_-
z`!&%bYvcI+6K|^T1^#;viwA4YXTiFa+d-
zmU?@SH}$KV?44a<$E`)xqggic5T`8RsFbT+knS+Z3d3Fr>lzW`Fw=_1pvd*+;1sh{
zcwBBUXspNR6w}CRK1Q1k1x43yo~tdmtJK1r6|SyvSD=8LbVg3nHsb4iXtE-
z>;X!KV$Gjg{EJ!?DZ$s(hSjq{0Qd#ZQNmt5*ZKI;Z_;_%55{Roc!
zdvF(6zh~PsHz6^r43_##0ysMz}eJf3xdt?`m@9{yNdxSaS1R-fxrbKl|
z?yz=Xl~CbF@@?XCR(%OvIeG!3BxBLYiilkFf_-LGFIC?c`-W$pJLrToW~K
z;QXV3VD&q;6w*p1L6!>Y(OA^24>JnB{1Le2Z}g|Vd`>0SF(hLAGM_+S8{WHq{7EV?
zjOXiwq@h>Jd+7FUsYuT}_MG+t;k##aThtX~W$L&JR!5J}R|6m0qnNhM(ywBkUlr-(
z6#1G88Q)LDbFL2fsrE(m&QU(fT(0ZE@b7%TnClinu-len^L0=tNi(5e9T$+*kybzAym6PcRS2zNUZQt9F8N&Ux
zk_<9)3Z38*)`^yH%NZx#T5_}zUb+zPe9o~WVa?=dEQaa@b{FNh2Oetr#3zo%DDjbhvf$aGg*kK)&4Zjl{wf23>;RBh-Ms
zgwOF;4A`(EYQ4$8>Ae9L-EnzIY)flbMCc)h8&VSrk#jx53R@(|;z$p;6RzS&(YI!t
z(R@khJ_QyKx|pqqb0{PG3aiv*l8G%?bJ!)$D7+Uo)ca(tpx*+x+B4MeU}0~$oXM7E
zy7pb}-SEF}9+(yQ!y&ITh`s`A!-c14TiHAkp$T
z!DpHjDv;|@Rt>?jvsFil^^WfANGVgE2qiYmv$EbJGK#u8~Gz*9w9e$G@s}0
z)jDp(!>23{+2DA4!-^Z}Ev1APKfi<>qAkr~GRsbQFCj8HnoCv68W5MDYswvdHFrdt
zSIUW=Nbc0#@5r;AZ^uuK_yBK~H89q+f3QXsDt@Ng0BNri`|Qs-qZdB6Ibo^J$VRoG
zs(;?!TlyPd*Ht{x$M8Jiva+(58tXn+UhbSYM+{lvtae&o_Zh3
zN)E`YCjK^l
z$5+45x#(d;8W{`C`#hkME3;*S(R%JxG0q|M_z?~8{w3R*0c9u*Ohxu90jDAjBoV=u
z2$tv0%#&nsI$^fQr}W9)5m``r{UiXV5JT2W`2Q&)C=V|kbF$kF<)$#HzxE3Tkh6Zu?$Ah2xQ>5J`3ow8QCi~ih!z6E0g24g-
zypSlW{r-iJ+TVYyzUD#0iaDP$Mzyg9I@XZN#{GE5`0~ZWY!(^{+8YfL7`<6%70#V^
z{hPV&<@kNeZL%f${q^I5$Jdfq9eFSX3}z1&RT9=xc(B0VOg7X=dr%LD1zyh5&hZJQ
zPnWf=@WLuI&kPflYw6I8_`s6=5w#WAi?QmmFr{@``m5I`ug2L$YkMTcQagw|s(A(_
zVx5#OuJs{4h9xx@+u&T;T(qLw{x%xZHbQ{&gw4(8oa_Blho`?AAwjAp@0T3ALgoIrb~?sZ`>S
z%1dyLH9qa#TK19Il}Kg{USzT$84WG7BR}b|;rOmtZ&z6w>jqzIZ-iYzDEQYUbCxMq
zMrLy1{)uKa%0QlT2(IWb$tEuUK?RNIM_ZNuPL^J*ckodpy2gT_ACr9|bqwXq0aUyt
zye+wBl|kfnSofy3-+bUwVo?OJSAku{UfrVInmcZNo|vIl>tf;;K44i6je~XR{F#;N
zIpb&%@{ihRs1oj}2z$ehyAc$FwZuRY3h~L&N2LCNtvnNbHlGzvAizz2dizAF@E`cgSQxtnX4DfyYR!L%aDV2HpJe_@Z!;a{Hi-f5u3MM)@toibG~1=yg$C
z<636|d@1zA7zXr7wD=kyVk1K#3$?C)d7^Fd-Bd%ri-xB}A-_X&-NWQ=gQf~&+{=9T
zcH`Pl>HNmw5PwdgD$F7X%+fJ1FMt0ntVhn}yH-#rcQD8BcCY*no!iIKP^BItHDs!c
zk-8tB2ot=Ph1x^Vm90{MaiT82o%6w^D22Q<3YNFf`rG>7=GYQu{h0@_
zZN~`yumI7mua$Gt@avIti`@KmvCC2(ntrdC;_q)U*O$ZG2)d(Gu
z#Hx18l4ogyk*Y%Ma!h)XG_O83_7X>F(gn^F%=i8{UY(7Z>T-a!%mJZ4o1s4o4AhX3
zu0wNNu4bwk_Pat+uW2y$;&4jt(^h>{*iot6l7y_dl^`8ziUAwTdhIAkes1szd9OWA
zdm=_~>>wh<+B78&itZ|NQbqe#OnBn&-#Bd5BkChWT=OYuASmaax9hF#6cX@f6Qpj1
z{$Tma)lQVgX?8%IT)e|wZd$O*dpZ8w8J9B7rYb|BtW$u_ZJEu;NKwfW4?RwYDdlfD
zj5oBB+f>v?XP9g&X(5i26qRN@K8jq7Xj0OcgllXQeOhUEe=?XcO(Sf(e$igaK~ne~
zc8n8Gtk_GL3vR}7y>GEb2dmYK<>%iuXy0aTXNbKA7v6!Yfo=F8jnewsJcl{>$-$GA
z=B56gT(6Qe8c(UQ73BH@P#?{N2K=cHHXI~2H)xb%tW~5NCl%`;h}Ia=pF4R1)2N~H
zvOb`1vbAUz^IpSXHfRK-5~J+UIYWd0==%FGmpHpTBt)IlA&?iuI9k1mjXXAT*MF&_
zQ$(ajeE0xgK>o)b(`%l=&U+|3Q$~*qeDxWc?j&06FSVQHMvwa>Zw7bxJw!Hj3>AyZ
zI96jX?r#|~s$`!bO2@C#b7ZTj!SApF{>+(4g?dy5DjR3Ya)S5-Y~Z{7d-c4QCf!mAB+7!<{qt
zw;*pu8k=sB{&(p(N@R-s$D%F$zg{GuFkpnq*X7XI$z46rP(Y=+t;U`zvJZVwQGbOX
ziY{`39?IIKtBi)Of%eQSW@FpVPs
z{Ruzn!@=I{l7(ezd|m4GNdS04nWB;o0^jCo9@@pnn2T_W{pyAr)p-&XeRz0WYoTolB>E%``uTA)VznY
z{!MW%KWOY96C
z4Y&-rlP;$0gvOM`OWL7hhWIhVECMW6DX#>p_U%?C$bd~CtJ~_ajHQ`Cw^W`#`7oET
zDQu=(05;KxDh^t6E|;x!cXxO2@v+Afd>2IVU@It?fyj30deriimFXAlrcG#RDNzQK
zyU#iCp}O^WQIp9C#PDuR0O@aG^UY*KD-EnQVpK0Fgq0!yv0sEHmgtBFq%FG0Y{f2FZh@7
z^eO_gV<$HGt-m1T1MB`fd~vUgVpDT^!0p?;ESeAfR(`ZrHn!vJcpSM9Prf&iYuM)!
z|2~O!fbfW8O1^m^WcSb?kUnBj6l*+%7Yf0zE9iG|p0h@>{Q&*pPW|DKKL!%D){=qO
z#~H8H{ZfWYlZ=Wm-_m2im9n<4L0!<3kiv8tk9xDTZX@Oax5oVsXD{S-{I}uG+<=
zcC&Jn!S9k;pWe&JKOUGaXZfX226J}x{&b=2V&&<+e;EAlJ)mY7vN{+O1Z0Wlf8=*o
zX7)dmKh;2y|0BVJPG+q9&vu{%^ILUcLEz}0Gl{HzBMb~O*bgXZG$Nb46yIP{K~hjM
zP*561QU*rG@dB235WR}Z#)fp)IZSK4f1Jw#ePE^C!s4Q~_0#IW>f)@oePsjn*4O&e
z;Y2#wNPqS9*uRG2zrG|_yf3RGA%84F8$183dL*&dbvPp|o$(Fh}~
z?W)5M%qi7Q`N?4(e(;#5?Ikf-UZn}i!_T^z$(|$Twmef~M|aF8dO1$<$>iG5X@y!<
zcd!f{@eH&DJng?xn%pg6tLIzP$k$*`{w5bWwMG9~@&w(al1rXEYiCVg@_Iq-R6RoI
z{n-TX8Q2!7zuBJ*{8RP`+TYx&cj~5b9RChtY>+#;7;vV)iXkU@KS%G@XLzbPAvw%R
ze!AAj2{v^xU<%<<9tVFHx6I=n3b!Ofl4dEm^I7>V=sFx#%h
z*dZpkr9G_iDv3sIf7HQ$D`_8pfBT&2f2hYln%u(QsUB<((CvaaizXQ
zrfe{o_o3kLCIp8VOZB6yZpEB0!995v#D&hhxPTJ;_2!jDsoqbtX9E$>45{lrl5t3A<@WGJBp$`Be?fjUv7YH
ztPr%j7AvE#2N6xwMb!CKsHpJGHptvLifc6lh}rt?d6+oVx87L(KYO+;-}21tiR>OD
z71#v_{-v6%G$Xnv*u-DadN;@rN`)=65;L2M>j>vY
zIb?ePL~d%D_+)A|j=a|-IK{kBA5bPYnsL#`&#bd}FhPtA%;2PE;vxNHJbra8bsV+T
zzZ8Ie_-~N(_|f9RHG|`Vs@WdW*C8|i0IPZzBDd|-5=VS
z+){7YL)WCY2vYuVp?N$I82i2RTMugjdW=6><|$8i|90Q98Yb=GVgC{8ORSnsi-2+x
z7tK0}AnVa=;^7VOzzL&S)TJiMNOW*&s#+z@;Rjm_5?<)5wq)+7%x_t#VJ61h
z7{(m2%s)v-f-{GAe0J98k2h=ou^b|}q9MV1uBvkz5Jyh>V;^Jc;lvpx{dA2zy9;?dZu##OGl(pTomM|dCITA7?s1>
z1G$01k?-d&8kgeN{%5CC)9qTWh`F(0DQ-h9j|>+9zdnEU)u!Ofpk`~lSO4xSC2Tr1
zUhW5n{8%YS`CT7n(2fAAM}S`pFsoo$U4T8tINW?4hL0~zJ0=ur$i+mx-LQM^r*|Dx
zHEcL;L+F2D!WSz8rabJ2fWIMk3Bl3BPwU!{-y3NL)t$e|IXP59l5ft20V_znbcuv)R+lQ*i%ueeiB#v_apNJ;TF57
zetP1yA*E^)Iu+BO;WTz{`ngVg<3UarJBiA1oY;Y6uFS#txFw@QB`Gte(cOx=@RZg;
z8LnTR65Pk^iKd&?I)BEKVwTnontV_4>P_NHIO2u8_8-()(Br6?0MkCRj7oS@<)Hgr
zb&PVIdXWC5{Ww-fxS3TyNU8mBNROd2@hlu|28+uUA{je;z14oc?ll6Oh{v>Ye`UzT
zw&AJd3n+r3Hu%d()H)H-(1uFh`p3^RBXA2IzU|`9d>Jt;`s@2OhXW
z)==KMj|%uZdA8GX_b>r=`D;oV&5@2h1T3zjpS5&PxQqjpqvxIRbFs8GKM4@_W88UG;a(T|SY(RFWJQx07GA0={UN6$sDPao=I_0}KlH
zsD?AR)zNR$Shv`p;Q<68AB8VJ57eSV1S7B1DkUz3SvGM68gp>M=-dO#7i1xtZb^>g
zCFklY3|#HlL%O9fCi8?j91)rsX@p8y8jgBcA9-Nuw*ztI>@>L`e`|Wwv38Lc^hXj&vk6e*k~s>~ebQdUJG(m_^ckXcP{amdKvkW6Ap(PV-^A=huL
zR66$Tt#I|?pLjMDPD#7)QhJ=~?$If2Tw$uWr);8f1cjG=7aw(KZy$`6LMJuBGe;N3
z!Ee7LZGLxC?RoSk(FZ26Zqv_>EnRH^)HFZ|4nybi+$|L%9}cS^0j4^ndyy->eUSRr$kaUc}yoo
zcX!dEw1zYa#{`S+RI5x*KX)~-C6$ZMt~8|9ffpHFVjMVK
z)A7T?Ak<#BPMMqni;sti;Ur3R>bnx&^rga;@XS8PP2gZ7ok&2C8|lx6;}n(lsFRZJ
za2S_hd>iHwOK(>QT*k~?{jbaN2u=J=aN~S{ax8UnB=;0^8e>*>SQQAm7e^3_1=N
zx>MFJ^*`uuMio4sDWC(o18;F8dT0I^+$6Cb0h0I%Eiy=Wel9YNvUufnL=x4KD(vJU
z3+`BSarsx7@h#L3CLFaE@!sZAE=qbj=IO?=#HmG*h!W;1JbEIcP?onTBC=NllKD?N
zS0DGF3tdrF8e2%l8zO{1Ud)BOQ~3SuL0!F7BkgnW=7{){pl*O0c>IuABD*|=0-^N`
zFeQ=f0-fnDwMsqzuC-&=g|2{0)vZ3~+AlhcJPGIYFKmzZ
zVoLk)BhCZDeE<9c6V2uWYzzW2hSmWc-l1VmX)@ST^hCRxM1p)rNNqo^EljzK3SMb6
z^x>ld{cBV@LtE~Lc{)*2Q{501QWz84q
z0t&*M>|gdXr|lV$r(8WT3=1rk?|Pz%^-)DLuD2=?>eCDJPD>oH+tc;HGg|A-}Fm8uC`>4H*d&^5>
z@xP#=%%-E4znY4}+$d=;E+L|S{(GWOEi
zBMn-_^IWjyCnH-CODD7wG|#M-uhQrZtxw0NS#dzy&$b!oaVZX*uY!D_uH9G
zU+mu`yZ1vD#E#l<%yABU8+nJv7G!(@-^(|fe!a4hg%*w^PM%tXrP+7R8ivejy+Q0lA;xBG1QoQ^fB6&r}rhB}vP_#XS
zHuu}n=Bd45qE#+)(n^`<$XPD>>Q5mm2gTa#hr&qAzhmjhrM8L;w6jSZ*W-B|QJo5=
zwKbRb6ft!X3z=-Rlk%tc%(mR2FBoZit;DiyrSZsSHch`NUwf#NGB&VBbYJLBF#;}H
z8#B-RRKFEmK(CO6t$1b6@Eh@4NKIs?E0kt;mu9#uuDWAe(bNUtX|}{z6!lnhIyJ*a
zjoD7aY#Aj%rj4F^@QhYyjGo+jR+st)Lt^BvMELoF``u9e1;RGxhSjHtns~!gv0`v0
zr<0r0zVD9QGcx2z#MBWU{=BE;m;;hue%x!!n5+v$J0bn(H&-3L^>^j_@b!V9r-^;Y
zR$KYWO&vfur?5@V5)Ct
zqv*luyq=P`n!3r-ir!B{oz7;8XW3`R5Y0O*WGVgzcS6wbR>p2tKd)B95)63d{;=|U
zgjMT#TWd%zy%C`PY~LnLOJ|C6nunpOdeYm?&@4@&Pef}KQpSVYU_O@mZYOI?O6eId
z?sFt-aF}69b34E7j>2l;`!sSdlO_gqw*ZlgwL=(@+$?!Y#qp?sT=7NTq1bOS*!zHx
zG!gV`uY!B)X1EcJnXPjzeIVUbf$NN*o|Q|*%fHbA;(7JHC9un`Q+)5=0;{t9oR#^Q
z#;!?rrY8?TDBDI&3-nsxr60m6%c(rR+J-UhokFcCgHk)NSJg$0mKLq_S-$Y$sny`I
z&URWvtr^XEm#Rj-3t~|5$s(xm32)fqQr9t0{#N)oHK%_3;W+b#2h2LcTiu{$Wtp%&
zdT9>!dIw#gEEqpiNHXy4CU8(z5jx!G)xs{dU2B+cSG&HL^IHy-2VMxwX4fW=Xlr-w
zws0kq$O1)OoGt}Jr6g>mX*9u>I<4}UicAdnxl!*lA9U6PBeyE)awLXzx+LcN<;^AA
zEV64zu~}|`w+>4yKx|d+PkJsZ=KT_>1;qt1|Ih6EYFgY~X9T(_B@u?%t~%9Kcm&8`
zOY_!X?VQ|15{qNT4p#r*PZ5T-qx-+MK?6B6ZxAnJ;RMB8Rq9UJOX
z(RSCA53tV4E_2AZq4}K7On=cR2$7WOkY;E%74BYg`m&;}fRnCMZfcF@0@yg~Cr)b^
zw!UviYsIG+^Xk>y8B5fPe;qO&d2UzIJaOKQ3hUh76{9b
z8Q!Rl?pZ<;n71VSa|3OFfI37kOww#mvcAnQLF4w-^QdLFPw5?g{cUw
z#H*kZ_OT8K2Nb^_=|D7tSPIwl1RZ-Yhf<*b^bP;PZbRQ`p6-hGFEv?I=h|aWuBOEWw379g)NtUZ(77iX<|b{+J{>Lrmy?_Ju~_>w
z3X|2ZX}n+aSbHh#dpY`lNLnzDOi9+?V3)Z{*KDJP*MR0g85QTY2{L`q64_J(P?)h8
zQ(Ble8yIf{_Avwsr82lFsq)tZV*}AQd&*C;bpw58r6;a=Z%O2*V#Oz}q)NkVxnD@G
zQad`^_MGAxi+-2jle=KA*yOmF8}hC
zbze;hKLPgiSdMdY%`swfP9+|-%H^)_PkPU=RaVWtYshYh#KrjevPj>I}l+k;8
zc&>EFe+Rwq3hM%m=+uPbPim3E-syedhTvADxoiW%nd6HAsYN3z!ImC#<)!Nyy#stH
zy8LJQp<^W3r5EYak9H*wVg(WRx<`&83YVwDm&=5KxgcvB{&aKGm2oZ`@;3fmr)GI?
z^VznWOurX5WuEm(8JbvOA5F!6eV@SayRdpT?cznDc%>IK1frG-a-`}V#7<4|hgT1*
zt41&Tz4G%-p7WOS7un-J&7rF!q-Ce4?Wwf3Xn}ms?7gWwtn&q<%dh`mH}QXE
z6Avt`oHxl|>R=22)BlM{%v7^=!c{}}u_KC^wyl*j#x>TlmKm@0UJ*Z|X=s3)#gbCS
ziwJ$VsMYOdAG0%a3l#&xfgT)l)OpQvAD8!I!t3aN9{VwmrpBBmJ(}M?
zpFUMUG>jsJ2mH~irEk*EHPATymP|N4-%qR8w&cAtfo?o^7NH}1shdZLmyMWJFPQay
zI;vXb{oUcAnqkJ)zKaB{hI8h=(q59zKALERE%Ycxn@xu^zZ*dt?W%YqNy)jmi!_}x
zcv`n-!vJDTRXPEeAfqb7R<=E*0gR}JWkx-UYuz=DOS&qCUt2EigWi|Wuvl$oTz%f+Qc@mGrdW{t?QG)nP8O)mJWNTZ3E`7%!@`N&U@C{fh!;&@G4u;1_QGBSs
zwWC+0SJMAS+&cwn5^dYU-Cag^*|u$W*|u$)U0)er*|u%lwr$(&s#|;Cv+ucQ$9}jk
zfBX^okdYDjG;++fR?acUSZ{*MtK|kisQd~lv-}DwtIxm#b+_;>jo{R89Kltl4+phg
zhNXKf37uVQSE0O%C+du^m^Ax4#@&p<)e9A#RtTGvQ$`7d=Iu}Qi>k&Q3i6Bk
z3Kk+$@B#++5BdVY`?GNx^RyyuM>PHrjZKu2qh)2#r{m!h_o-Q;tFIW!Mr#ViN$XC3
zU_}*7DZRDgsx`)xdA0`9mP`ZxB;(dxNI7KnL3g`l&fb25GD(M5!34Y|Bg=nQ9
zjw!B>$6ppAKo!WSkb8L=ub-TzSQQhatZWt82oS1resc7|s_2s=&B#+L%+#hs8;BwV
z@4|>o?ty8(XDsNE3!H82tR*mDOBJgx3$^3ejG8~WU;i3KI#9DV
z4t%y*6`TXE(!4)d$E-aUpoK_(c@P|emj;tAZv8S1l_fi#qAV@FRsUvIkVK$Wv_{o|
zVZmD!TTH1K`wQ&-eEq)%ObIDwD7$pK@4R9
zMhp|B9C=B#;sWuofYeBseT;zt`b`q8#0%nm)oTTG&k!pOJR}r>xPGpDDr7Q2gvuRl
ztxpJ~|JeZpwTZF5{YPQo1E`$$DewbOU?9j@U%cg1
zA(F%p|HZ-$Q`HU26srH~{~7O)wgcvd5L8#IIHWiP%Dq=->N<76b>yYP_wsfV^{uiS
zH!w(2K`U{Wg`$$!9=2+z>honmx2ZGZl{1v>+9Y;zD|Yt+>b8xx0q_*t?3<>rpFd0{
zC#L7C@07-6US`6D5`;7m?3Jd9m*PvJrO(-Z!Xj|jxm?Y|HWnRUXgpNMx`eLg{n^7Q
z$X&j||4P`WHFJA<*jGxX^%i69ZgcD@qqnK8rn&EX^g7|Wj)F|#_xsaARB)*!IHhYo4y<~X?UvU&gH~xWoWQuj^?LR2O)TL^@wLnib
zlW7|d9rOU+Eei;!!M*3-eSb7mnB$eaLX=VP^l5yZQSkPBfwK9}$Z#PM!I<#=om-I(
zExt6CKgY3~02a9l9xlChhwua#gR6bRBe-vV>jte>uOxrFZq#0-oGY<%E|On@rqCk0P
z{W(yp?3)N*Zfun%?!_IsZXZfQ@&YVYv_sS=LTZa%0XeHoN$#d_G9vv2W&_6|VpYd8
zmeV|%wzi2)&BnnKpv^$W03b*EsGY`Of!k$}dE44%A$`~kU2O75+4@&X>4;ta<_1YM
zzc#tYrio$LjyaaAtPg9++P1&b8e`j(70La{QykB5&HOsz=T&WnL$&SU%Nn+8Itmx^
z3g~elAel>vhqUf;t@XD0@&d{=c-)
z0Ka|aAn}iYI5$7{cUUCZm?6A+2v~AP0vQA|fKV#vAmIf{dgM1$J8<*<`uu!p2n#TV
zACd{^cQn{6j5OgGhBV=>buvORfSmO%!q6@H$gL;idB_o?czJ&r8vU3=0vc3v@X6RB
zKS%lYyJq|~@nO2%0`f=rm3ltZ(g4yxS20xznM6XZfwtzyf0M(I!wz+v<$VA4t^LcB
ziRynR?dWNKxiK;QSFEzaj0DzKrZ<~<9fLXxi?U_|W^n;SL1p%{!bw<3c0Zw-Usc?M
znkXyN$$2Glma-X&*EPsH`ALR#_B{;F||{CqHZ0(?5b@pnxjdLAt8cmpt230xW^ElF!{4of>8y*4p&2ZP~9rDGq+|D;Ra(MNa)J^wCJb*bC(0OJ(A%QpdJ`i-|UCsT>_J|OKB
z=9WT~R6SlcB#W3lr5?Ywe*^J9OFImIhkNdS0F?P(fNI;$(IfLTO{97oSvLJJ43Ch2
zt)N2O(ccBDPjZd}&YI6o*Q>HUBp1!o$|yAO!GywvLU@1UgSN+^B-pf|czl@P7&_8<
zTe`yI`;MKb=pQ`fT&`afY0Z68bGAp36T4Azzs<5EjGQL!2C&Rmxua+0tRoc%^gSK1
z3C3Vrqa_K9HA%S@)sM+~6ID27PS;>cVATvz
zwP2Js+S=E;K427g>+~aUD$=}n+8C8>k*X7;mdecOdukh0m99v<87yT!GZKD?Qa&)zQ(j38%bUqS~5B_SFs#=bt(Rml}mw)R%Q!Y0}@
zTl}Z_V#asi_FVP!&yU^2R%34RXtXE&F<7np6U)TRcQI>xpDlLn}
z0RJbBdL^0~97I#JG0MKy3;q#9tK{5^0fr
zOf2YwwbqQZ&rY$#R{zaW);RH11jD!jv+KW;*UE|&hwTnZ+g0J}b`#h*dBc#|s~(?_
z7A$~VyDa}w?j&^3Q=;wWp5H9Ta49Au9umP
zhwEH-PmfP{->zoVf`W@ssCU%CWUtqUVDPX46gU;c9fPl1@lx#FyiM{|=I9wY8vvv-
zy>y;MZ-fl1lfMEJ@sh9Q%@e!{t(s5`oSI}Ib%tO`^c$+`xrYZq%%cYI563;Wga~;N
zzA)wf2d3FY4fPrSth;H#k(QUW1HJKQIkY*Y_XQyfa`_Ho&-g+xq%`x=aFP`=+7bRbqalNTDpusIjRQ-wRfp)&%IEJ#oHj
z$ZF10!(n*S$)KuG;SV0`Z!;^^++#+FFTzqr6qujAlb%aUR2+3UD6drq8JkTaJ;)h<
z6gO^td~49`l4~B}SI(4#{qaYz+uq+7whvmxm)pT1UX-Prp|6iq;?!|PTW6!o;f?E<
z4EU6aV(L@5J@>T%dheTX4s%N;!rNh}!sQd+=AX=6Cyn~=$nSrSC=~H~xfgzc+VO7-
zDciq5m6l!m{l(H`cH%-%0ZBfyP|y(g{8YgOTn&4EVFwgSV#@imL3O>Dy0l6*@)tod
zJHgZ7c|pK$fYO3GQpqVz@I!k_hWnk#V%O*UJJ>dg#vSB!a}Wo2i9U*~AU8~nNO3bv
zg6$FNNfdKkCPn3-B;k3?s+lL6i#M+lUVL`pY=
zy_~7-l_~x3E<6V-?3dy>cW!1AavE%*vh#Y$BSKv6v==wb63fZH2~TshiLH7ENipNv
zs#4>_IRkLqL$=ZpL1<&e{Y60c>*;XB$1$t3j1AlD$yK=cOJF`HfGQodRiwY!IV%W^
z`UlvplTtQ#Vl!bkqhzY$>XOx8?S?y)dz=G6It!hT4g9Qi57x$!wELJE1tZ=r!kW+L
z7pU?BAgF(C{;$l{e<hD3dk#ki4ol|7$KZ`O)>jZi1Pw?uPSD5q6w3kzOzl-=M!voOj}+|o?V|_Z@>Ou
zF=bH){QruncL?DBJ4`j@OfRS;mV^~Dx=>_({QdnOFilnb{l77F1Zfp~!84tJ$0#)P{zkFNs_8hZx|(R#6%KGh@!h^^azo3)&Jv=l5A>N3Z~BEXI{nwH%Oj_@HdN
zwM}Q&^$kfITYaV(p*}nU#JnE(X)&RAnmD7GWO)DL8NJ*Y*+JVuS??I*+^Lp}=p+Wz
zwDqHp%scKWcb%!04u`!t^KWN*&vH@qa0vM%+-LqU=6oL2%FzHFC=7y4(qR|=THbs8
zV0jQ!cD3t-j?Q&I+JA^b!p5?38EhsJLLhb&G!d{eF5^tFZ$ASYNh;OEnK*^ItvdS
z8a=qAd(8f_*BzxQ*o77gr>n&#PiaGkdQBxvVgt3-WsBR=^-)^t0wW1%4sZqJz_$Iz
z#c;e7OW8FXeJc&}q6uW9TOIJbL|HXZ2&+@IEQfx33jOFqxgTJsIMcu&gCrWDpjkvu#I)u(*dC@7v{m8HkLxpD6rw*mNkZ$?mCOw}GD~Fq
zE71q`C)Yz#(T+xCXK^K!o775sr-?{u;?&I=Z8FL|bzwX6fR!kvM-5D!*^j-OvlGm5
z-llCWd$jW7e^MEajgmV@=1NLPl$=jV*iE;Qn)GxZ8lgBj3I`@9JN6Wy!Q`{r%80n>
zbOAymH;{i&3E}zBnv?aWgZfEMCXO$}rThRwK88>;m^H()d*6F~fj=;7;y0aa4KU1O
z82Cb?^LW-6GoVL%nzr?iG_@>?6rGc{SJ|LkJ%WzU*vef{^P5Q?Vgro<(A4mWzY*mzx%Z;p?%g7FwcEc&oMyw+U7wf%=
zs5cyR$K|t)Y8@_@Y;yve#$;CH043-@qc8%L(BulU3ZQUe
z!ar{MK@i&sVdV8GVd~&jt0A4pUL<@rbBHh>DvKj
z{q<;V3`B|QbW-D?#yb3~Fkmn`^hWD^pH%x%(X|FG)QNOJ60$_$8n!E5-&s~LN$5(q
z9Q^^oNL3WA2LU>0U4?67FggbEzK*>-B2zL9%3!3h6)78M@|slbQKsS>slnlgBBZde
zLBhV693vM3Mz#zV#zP6>l!<-Em3x4}{(QIlm<@Fd!z15rURuu*8lL-?^!U@sYoA!q
zIV%N2lK5z1TpAaJoDvP2^F?)Cr{~jR;2&9}^@pjlf_^JK^mN
z)Lks4t`x9L=?}1^%#faBVzzO`yoqI=J#jRlyQJnDSwmvpPRU%Q#vHR~djoP-$!l&Xoh9
zbs@E=Y;Yq9;B9xH7p)jxQJqp??z1>Yl2KOHoxMgjkvCLQe+0)LIn(S_zic$2HrQa7
zT-}z|3WtL~m52h}QJdm$CzD3GhAgGAQ|rpjg(8U=T(z#Ci6
z9z2gyguZk;6_|7b1OlqI%V67@#8uUFRBM7%mDk}V`I9?Hrnm8N
z=OiBsK{&IaP$EYKm-tDDsW|4c(*#X~FN83gm{&=()}%97Qvi69#?)wR=o%yo8s;uf
z$FKsRJ=7ietMfOT{EblBN2W1XXR3MUX>Qr8^C~7$TT!u2cK0EHwFuBa#OXP~CaMR_
ziYx*O0a+1Q)ia)JJW2nl*;7=BN3sCOvVotFc|YwqXCkL!3I#7Cxzs*-d@-l=M|Wb6)M(XQr29oOdAb}41K+%;XuJhC
zA8!E`v%xF`qA-nEK&UAsm>F(o)OP{Q#2f2$Vt`U`nH!RSz^Q$Nh(>yJq$2Vo{(RKT
zfgOBKFa|>@LH2gNAHg6pY+NP>wm|}4x1gKa7)bN+mY`iDfBw1|s3zVpqj)@@fVJxm
zRQKEBS~2`JD~*M^ifvPj9a=)u1#k(<#0|--9b>@@&gBmEeCN%`_!P)18IFWWB$G1k
z511@_obwor)E@xmB>XC+%u**YxK1+uykM>I=WRJ1%7c_g)(7TB;@5?nm3J@r$|z>Go8eoa+mi4JdC5b>~N0kGCj1emA(%N*4I7K
z+q0NEHZ1L0bPOvirKIVIkCjwvn0%I>->Bb
zS|#Bj(#Mv^JE01BmPs6gIBWh~ma386_8S41$~xhyridlFq?Fo%SMg%@*ILtklrdghPpx>cL2{TTn{IW4MkCFqp-V2qC!kw>8@4M<
z)kRK=Vv3ssnq%O-V8zu6~6
zs-G(O^3U_KXh7_3t@I9*$7MnF0J~Mt^P6jmk^Kp6-oi=G#4eWZ*yq2EuDgYgi-d!H
z`zDdp;}43Ow5|68CF!^M4+20(eVvOYLX0Ne@*9B&96JTn1z%5WOP%>Wuw-e5l(k}kf_hp9^#vP4PRIiU0N
z{S)wU#^HEyxRmtGs-Jgl36X8{mG06Dbw0Jc)&BLC`e}103fBUqy7E`cVmaRd%pr+pBN_h_aLg=+T+yb_w
zk@k7Cuq=5A2G-ZRK`-UeD2vlP0SNmMZ*Jj|l!FS58OnBVTwe2h98!?-D#UG=BD}^3
zeS@>nhtkGVT2hhhC<1^Gd=Hoy)#NTx`yslopW@j)N9CzIvMzW_M*OQED!BasYGq@cuga85oeV{Y#gvI
zeG=*+dems);MJ&Y?HW*HoRi+D5Pjo`F|Ns}kAO~Hnv(bTw0TcqkUv!tBba=PpU1Rx
zAXeIb|LElCj{zX1Ywamabg&MVMmj9D%NfVu?>BA*j-Vp!a_ClOURrQgogl
zI{IB-0EuDx*J-TNi5dUP=#%P+>nh;MrO?F25gill_!ppWR2U@%H^t9ez;TnTRY^f6
z&p)A1$ru@SVSK=~NVFlmS&28+Wi7RFW3f1Q!(d#YBoO@Uv8MGYY@3I6GiKCyW3m1p
zr?J?Hd)SxsJ(H_eDTb%B!|FKwTU1%swp6)+lHl!fUsdk#zX?U8+xyALWL!~^`6hL_
zysoOEZUCLmkk~!_R}mq6Z^UMF-D%(cFAur;R!v$TfUpmdM7@NS!%sN)$0QWFC=rd5
znSR7sLc@{Z>}frkiX_DEB-a${=UQd;9}2mLSYmH<-3z$!hy*0{hlJwv6VI3=P6*1_
zNd!&71wulhAT3dYnY(MKT{L2Ru?hEAuR*_>W8nbyN2ns_eJ5KIr-DZ&{Vj4t2V*|6
zJ^((IrHrsxg+67!iH%MK*pxh&woG8rj1bCX-+;5*Gr8CL@8qZ)Urn>!z2*L|!J(#^
zF&Ol1VeDNJ?87**JEZDonB;xBUEvQz9nue$59rO^s$Jr&UiA-7+B>#u8UWJPP16kz
zUnt%S*K=rBSk{Z@bKs-*(bXQEH#A^w1+erCQ4RzQbH5Xz?i8sL@eL;0hgE!e)@*bM
z>e3i`?Y#8iWfni=5-LL<{vJ+Dd?Q(Ka$LyU03xBkLw6CY%3tj02nz5%5{
z7__j>POUj+X+Aj1mYrTKGb1QG#OzhwAq}veJaCV#EfY39aIr2-P_;oz`*aZ=gRXnP
zpAXD8e2mZAiU8NZD#p}57lhTZA{Ko?Blz$cyQBM`y^5Fhnf`o)Z{Lh5zkQ?lKmB2t
zBy8Iskbr-VM}KCy$F+}-jmZcMX8ZUA6bq^R47Casqo+oM2Gww8bQcejGT9vm4N+dV
z+p-gu3uu*JZz9I8Y!GNz^?ocWuxZHMQthgO{*sXVV>lWH_V1q;hNsN7bjPXB
zFO3<;)6HpDruVOIBM;@iz-K(P#T`Jwa}f}5#loJ)!&kgq#UH`?OYEk~%Lln|xI`fp
zhKXET5Vd4BE+>}i&tVE0{|EDa3~5ISyBT9^}*@9EfrwGA}_E
zH11_&SaC3Cz0RD2PN`M!`A{p)GIK)Bpc&wpy%(Dy4^#z`M!;Gm<_f1)U_Qpk7Aq^1
z%aurzbV*zUtgm!-6Gk;npqZ82Ie~Ezfp)OM(+ezk%d%SqC_}^79(wln{4NGiu?mJE
z-uX*|OCHk;O!UZk#)4|_i`hO233N7q8Xt^mpq@fKHxHq~jz2lUL!YX+t9Xub5%B_E
zv}BtTxTv5iJ#;0zkxpQ1mcc+wl~S}PEXVqEi1gy$CKg7~uxO|o7+Fzui@d~#ks#j!
z%F`!%=Lly>!!g($W61Vz-hKiAh!FlZurA=K=nLoD8vZXbT;&2V%eeMD8sU0v2vE)m
zQ!*h857Vh$Ibum9%u8#hcWi;-zcc8t^)U!~my^_N
zuH9Car79!iQoMEB=oE17T^k`{&(~xftnm%%(Q}ArFi5v{w=sDqlskRs7&BxYPnrur
zO&iSX(>Zm!)uvZA%>n?4ZfZ0F-rCb=H*^mHUbBsy88IqZ?$-*{;sxoUdY+=D0sNQ~
zi7e>_EPEDeVJa|WZP-SlO;xL$zt>Op@N^sQMF7)ljoc#4)e%y?u?gm^yQr2-t%m{J
z7v&}+-C_1YEW;Yc5Pzk`MN{nV31m69*zU}bf^be3ft(`(D7=7Ct)TuxjB^F*3~i}F
zmS5L7YUCQqcNbT%^}ddoz;6KrP66%;a_%l1=yq
zn65IR_5jx|8%>%xGxoypgWZ#)+f(wQ?}
zd7@eQvn}Trx$;r;Im`{s?3}C2a1yOc2DkvD_H)fM{|tgEh9NTVyzHwHOuAa9cUaf6
zW^C2tX3Qmck%DNzaWgL4wLW&V!|}3@rPF!<6|pM}IFY`LCFdbl%%YwmJ6VQ6%X1>q
zeYFh2DPZ27$%Y_)#a6wes-w^LzT=v+qVTJiS+QV`#p*CEaqvSLF_IQ1t(rqPa)k3z
z%>5P_$F-2#y)=@BLY7w@nNM~|dpVVGh=Q|Gzf6X&;O>QUIX%HRsK|QTJ;s?<&OAc~
zZ5E7EJHXYceF99IdOlb{+s{?0RjKG*9&nUUnp!(?1%7WogUAD+3~SFGJ63$jj}
z0Bjq1vmKlpqEBPLtd>rW7;6PZaHmiB+etRy3Ywpg&QY~@E!p1F!GYPq1#Ut`Um3*6
z!ZPzG_BH)TZmLCOE3(sy^A(D452y8t>w}gG@8Dev=1J=#d?By0bsYibXiPh@emfu(
zys^7g&q@Uwj604g*9DPXJBk^ZIi}9-fXKF$xBP6>oMju$Ji$1{9+qom4g!=$@2m0i
zPL2eLDFhjI#Lx1XyL&%wcinw#M)VLD2bos<0;^mHtx;J9=a2H&Kp0fVN*;=W_&hkd
zL%Q%m>PDyRfzh7vW@cIzVarIpN(^g~dQydbhJr>hG}fSqX$x`Liv3pVfnkeM0Pk%z
zqWVu+MaA8NG^}54oSfl>oOv7ySlf0}-=|MCs8^yEl6qP-Qg8m%cl&EM3IT0KYg0T6``A5&-YE8_E6veV21;wudN6a2y{_bK!
z4JB1-sjum#rKYZ~reb1|DEscg0GRtJyf+Ti3e^$Mt6}$Ig{DW58r%>&xm#x7C-U~q
z)opiWs45uXWL<{g1*ut|?TyJqaBmXU{Cq(pfDT^q;$j>~Ez|8|v$AEv#sDI;r==hTYjf6c2vaVT+V6
z^O2o;Cy{j@lJ*PX;Tznh8U@T;j8`33vx(KKUvBm+kh7G>%Re*Y)N@
z^JNIG(e2IU040U%anK0)0ZB&#~v0Ko%Bb%`RE0Xav
zNTCsHGDs)inJ7a%VI%RSA&o?kyhl6_q)qB;k$!obpVD!tf7Ply>pv*)_5MU
z4zxX&oN?bFY33&f4y+cf$zUWDyBuJ}AIkOQ$eCnc`{Y3J_%L;)AYrAjx)PM{-s;-F
zpY|*~QmmW5!5I)-8bW!@gE!-?wYcmaEh99*oi6i2FAbCr-@J46j17ct5};2#h+A)p
z?zIYCsM(HE?E-iYYxbcYzEusNB`#G{S55v#4Z1ZrF_x+EfFlhNLI8M$l@km=nW);4
zk?QCU>=O^E>?c9m(_Mk6uI*5l7|cm+`V){SP$6Zlp>B{3?X^f3-KJCYGD(GyPaz*-
zxLB-I$0ji>%tVX`+TC)0DCgg(4b;PaW!X$0OfCnS_XAQR?M;zeU2)aW-!XufcVWlpQ|my}~3DoV77gSD5}n;*s6mD#snqENorqVCZnmv`h_?v_`6p
zlSyJ!rkXd9s64xM9(*%p>h;+8L5M5s6~+2aa>y15O4BWz_)r
zDkgbeGX_Ay<0#b7h|V&G&9$K!L&W2_=jG_Ak(-Xyty_$uORwp027j?axVC3v|qlcv(C7(Ilyc8uA!;DX_`ungglZoD$V$
zp0IN{evV6Bi-ync8tTIocE@TX(ij~U2E&RQWDQ_D#R}3Jk)f6bppIe2Z)icDIULDc
zljzKZB|Q9`RJ)1_t8>{UtGTRKdr}|Z2))!v=cy2@Ze?=aOAlf!;r=;k>P|4A-QO1>
z59YCR!9Q1fp~hGIYxFbh*I;{|6MF>L
zS7<=Fm}b??BS;x=&dqeC|7E~IR-?JAoV@~~Vx~fda{&4&|Eb&bWy<_(aHWSbWzoM;
z`}%GnCi9W8iL`UUsrayh{_n3h1Pc+6IjWeTI(k%7LsD+Fa1m;Mw6U3SBASryp&Mfq
zT7IlAyDiZe$Cb0-<)MHT2GQ!cwW%DKt^t6%8^qC`U?HD=Bpo~HpNOz(xTIaK@}ciq
zA{foFB0H3+-8%N*l{s@YzNdCXG(*zo47P=kHaQQ?39Q?!t9}vnAWd_$R)uJG5Ela(
z_n3{-Sj!@|dp563mpQg}csSjEBb}^Vk@bT6A|SAbcKJm)aP6fA4I|y%)@vYT*)ajv
z`FR){k#{qD%}^bYILjw)sBPF;yCg$sZYdd;xCM}&2}n0o#;7{-tJe_5KQ~n-hqy)$
zp7R`NKJu;lJx8^h6XMOT8^TZuM#bo1{LMxkoSa@+oSGs#b7^Z%c95Ml|Nh)Te;1l%wshlPcIjGA6!yxswCfXUq;%
z-nbiWbA83HQ}0b-;*IRn?xk#%l9Pjs4x)#wh*osh}t(DCo^2E{RTDq1A1wb=ZW34K~^W;$rGvH
zm+=OJhhCkU-F)gNR~QH0kxvk@yWWY$Cp=$I;oWbcCStu9(=l0XK(i%ai`!34iY`g5oz$w(ir9V5gk(pu%$0Q`~%y4x6}ctQZ)fawGhxE
zf;IqoQIgQn@Uxq&=MEAB)G3!_J+=NDp5tRU6J&pkjQHN>U5fCqxk)y4sZ6i5`hJo=
z%JZr*AuKibTZVOmOfw7>#vn&e_|qhDd0|9=Ncv}#8(X9>0~1q^!{st=z?)&pgjy*?
zPwj}*(CvO%>6ZulhZex`Dn#!79%LM8e*+1^|
zS4PzualprPZ%Te9%Kxq5HV8Xl^1>Ywu&1{4sD8}xe&1+R19WyLvAP1J#o=0C4c#Ma
zxcMLx+s41elYNfp`5!cYsOdBf+$PW@-dR<@Z=#NES=XeS1|RSY-hSY#H9{q71$%v~
z>1WZ{gRXaB)KXk;OJ!nmBzcLnu;Z@Ca#i;xVS8l6l9WK2qU#&iM
zEcd|Ey|GQFeI+5or(;^`DW+ISght>9`S>@nv2E$_Q_Yv)&FxFZ_+S5fI{bb>0f_%=
zfG|*ATNdeSAYiVt?V@$q4-%R0n>ti`GsBJap5)x1g?c!NUhkX}XT4$(myt`@bC{P3
zl41A`#B*M_D^LWFnbgsd?=aob^z!fH-!U+s;N@TTAY;zYY9)&Gr?VnH4d2*6)=ku8
zJ#3XIL_FV_G47bW9Wr4HQUJrVozj_|^k9Mq&3$s7)b*pvF9A8Nb)Li9EEB&O$6b|a
z>rV3NF1}w`mQuS!Y`;cp9^7UPwCIcsSe`PBmGB5IGbvITX|}utnqH`4K%r_Y$3Jaw
ziM1xcSVJekJsEK@`hRo%Q7*dNZ4!Waig0N_CE(`?YZ)19kqI|9eh(-#m{(DN(^$kD
zt0oyI#>qlYDZ5ijZm$#KI+=(}Hn
zog2e=HPw>Murf4#YJOuIC;Gvnxx#-&(s$bh?^^?s;K-vXK(?7(0bXy6TGi^?9O4yH
zwof$5s6_DtGpmQTGe`+f{$*R{0g2o86Q}*?>ZCQ2q&Kma#MdXpt?n}_
z?}HAio}7SYpV2NVw2i7RMx4dHyZUbkyVG*H8KHmsw$GlF<@bXIFrf+MrKSAkayVhM
zX>^+^H7COqS7B25aVPf;M=YHV)4N=zdyh6bNb9OrawL^>|j>O)Nl^lQdP38MxY
zXvs+gI>kv>lkWzp*r~$HYw_EEx9a+AxtfS|ibekW@<%sqv*oPiDARNDGu@Hw&+T%~
zm)T*?;t8QY+P*y)KviNV$s{4HwMD~%W!ANI^2^@7PgsUm5m@KMyC%GJCy+5^FV9Oi
zE__5tF}dJg69zqz$w_f)%8Nd3013EPZ&e9b0w%*0ezTY^pqqp_o}f29H22KiQTBAz{5v+<}Xq;
z@TQalam`gEX~>1UkU{DD0t;Blg@u5{Fhl6EyS3brH|`3>5xbEnf0v@)
zV^jpxFi>e5B^`sqTn%85H62gDHxG8lUZ4q{ScjkqEfeCZ=3gjV{L73dSZKYux&(o)
z5_cLyz)NPpU)Pa)R~W#O_yv!GXO&jZLyH$km#hVw#ErN94hZ9c|LlA8yp2QoG1F6g
z58TnsM7t(13UaFXUQ_E`esgbE^Tp8J31h49?t<|qQlR!`C~%YvdSo&SnU$AhU_<7k
zev*i`RY7TwDKNe-YwqQa(J3nW)i11T`04Ogr*jG*Y&>;-3wC!vcDiytRmhQ{GX}hZ!E=viK-M6spFIU8P-T5l0=?
z6u9dUFkpuqVm3d~PfP{Upb
zlY!(!=~f$uIt4G3f_rrgA#RQkCh3|~fcc`@!5T}vQa9D7>_y5+6
zfW3U1?y+e*!e(C7^DXpKNh`2hrFx~tZ&8ilf*_jTE5irx!_CVoKGJax--$yX0dm9~
zO3|0A>^2H|M^JG;xGKcw40^_b{BMM24G+>ha%c%rL4Tk_m-+u$^eS3dkH;3@q5VPc
zKw;EacvvFhU^%3R&kFy8-&R2cq~}CjEQSZS75jMST-ttn621Yf
zGcsDkPl7u2+Ydu^_GP*sKy^PL901H?CIbyv1s&LjDjK9FMIT$8+H(5MpWogz6RBAP
z4<+$jGdS0tzvZT{tm5VZDcm(}50=mKv>C(*#ygP(pJ>{>YZAhVxA=}A1CEHS8>*aK
z2o;!1j^dCU0}YA`tdatwxi)~*T)ze~wlI|V?WQy;WfrHDKp|Fw&DOzq01Wx9*j@e-
z$3z(v>vBZq;}5P0`@1QJ3D}mhMTX$xhFhZn^tH?DrfTU5>pp+N7;11oup)(ij&bsZ
zxTTvH{+5@l=A*}+jNk1I1qmC$-k1Iyto>|tbQ(pNs5Vwn`LHW;?Dg%*?ELM{Y961}
zH_svr%FeNufJ8AGPEE`R3$UV2$lpobh^SH1ODYgIH9pJIqUYqxzv~lga`F~B5_SH7
zzMer8Fk;81)g7LHCxydV|K(Ouk}hJV=^``f|M`<)$0_
zh51hNfvLC>Kk}ndA+k_}k{o1ze9DoWO5Zncmb)8N`p3hVOC37l_Y%Ri0b`R%^FNAv{(d_yuA
zzfL?)%x-83{hb=Hlx_MF49+72hgDuTw~aSLB^EVQ-e@Gh#+)uDL?mbG4;bh31^7u2
z6GvcMz>zkJyzPSh`Y1^QsAS(wZD`qC(>*7F^9@a%y;J$?0=BdCwwG*Z{oiDgQ=%xu
z8XY6kvieWaHnc3RZJ(RKyNou+u3$fScxb1l})03!|
zXcnMnQE*T5YE$s)-Rxh{L^J63lL)6_q{;c4xv&>n)-^c`Gi9wRbn9%#tB8V{r8NG9
z7GpoH!Gh#1L8DC+&o2wf4HjP%F{|;FKbGNt{i5(hPV2lH|2>Pi|NP7#>DqKkn})dh
z-NQUm1AxSjZ_k`46e%?P9{k^eoCG&@7r{+s0VjEWEpHQ
zlcPsnQ`Shr346JyIZ;0?+pT-YGLniOTV2zh>)_yO(n&e_l_6~e+S7CFQoL@S@?lxK
zM7|bH%o|oG#V7uw#R1)TNlF-HFEe%gySwNHCLqKVcO^&}vN4DGOt52ZQ8+cXFQ&7Z
zB6YIA(oT+NiO@4yf?1{85ayl$;@XIdrS^yFQtLw!bJh8=M$7l#m`%8oK4{Ks}T$L!Yiz*>(T;Z!b5T3B+Y}5&S*}R?fESg
z4el4Cs2pPw6eK|+6v^N?Z`*nZ7)WJ>EnN<4UpSML<2SKTa1R|MIM&^1!>bdAt@I2ht@(w|
zWHDVr2!B2$7L*#Hm+`E}4hRyfPEy@(pvb+*%Nu_+@o|@JJwb1TFp=})T*8Wj7y+0y
z#&AH1QCskhE=xvIep{$6@KeWbf?n8?B5xy|!2;(wE*TL27+kpw&mo5@al}~LbJ%xm
zdlgk=Ji&j7p*#Ju)kHh9PTy*lz)7fQ0&keNOb|q!-)JE3gfQuKdUgo!&MFLNhMeXZ
zSRSh5gD0oO2Fg6XFWSluo!jqf+6Clz5ZIXwg5%@Y;GdfES;~oM5Hz94u>7LO-X1#U
zh5J$P$N55`B>C_i517XUgcMt2qWXiLL)|26=7;}H*G^DZb^Rf`I{b*6$(<#5vfSW8
z2aMip2O$^JsT$qJIPv!DIqM`pXs(PYHnKpzUyoAeTT;JzoVD&&q0|8LB2n0oWw)D4O
zv8)X?rYlJ2(W9*sY-3d0swzTA34?wG7-U0KpTd{wcDM=9<gTvt9U+
zkCm9WrEVoxUV)p~CQ3v+8-zY6mcN<4x8*vO8IvVpmS2^Zb7dJkQTwOj3S9Zu@6yUk
z|3YWp5R%vONM%akN|p;XS0W}(OW-QE5)!BRM61mBYW*tORKiFCJ#IHC8(u5Vm9d1*
zk&&&)OkKRj$}mSM;{}{4JnQ1HKRNydYf0VEFSmS>cE!>)+F`qUrta80xMYDFU-)fv
zz9z~_zv2?JQ5C18@Z->!_4_vl6cT%a!t}2~@avSLl4WWLnEvAS45n<8lC|H*Ns$QN
z!~=?p;muz#F5@m`y-ckaK<@99o
zIqTq7kW{zGEH9;J+)HB=;*(6~+D%#nWppsB&{1!C7rTm!pJCL1M?V@5|1G~w(6*LA
zweXi{NFs_Re!oqs>A=27m~P1Nu*s*}q66j39DyOrUvcG_t8U2XbGjB3`f%NE3@NIF
z>MHRw1%7%*LJ$B|*>l(@@!_TJCQfp)PV!=!P@Uvx%mt)imvt=S3^qB(ZAcms+dOew
z`0{l+D{}2}eFQ5_6RPEirQ#Rzv$oQ+ojAn;Z{dF^!$B>Q8DpRLG>Fy}-N4540o7^;1~R&4XnhL)PTmThhW%&UsQ
zBUroaOZ@(y4MleRpA;edMH#!2Em0R9<*xz3^Aqnr7sQe+$W-@hNrzWR`(7jP*=gxcxb5D
zNL%u=^n|DNTu<)GK1vtZbm%P87WsfN6Of40g&}CjZ`ta)X2r_(Dz@X5GPhcr(qfV^
z-@Y`g%bV%pEGd4sn(kh+WxVk*4CPKK^I$0Zvyi}+obr2`h2P&6
zQN9jvy*gt5@x0XXywZXoIL6rFj<>^~Ej*V%a#jbmaXxnJMBmHjl&N5iISh@km)|(
zDpM+M@Z;~{jVY*dOwA)zm7Kf$;nSncGkf}YGF7~M|EX(7UdCx2jJK1GU(_T)r$+&(
z?oPq+5dhCgu{?WvM{~pYh(vcgP|GDTycf1gIvYBDM61W2%P`cWBioRyD5@Q*tf``X
zPF34+g2dmFy!2(2IR9J}WNcNDC=RCn2lHjn+G_GEnPaMWrW}b|2yfc#LradHQw@zG_<
z+r-nxb4fM;eO^6pePa9zTYGFj#e@>0pFOy^
z-oJcx1Tk|+!Qp|gco>sC3(Nr6tGPPCPj@7p-Q!L0zY>Re;PQTle!1st3(k`Od4y9*
z$Mj_Qm!mij^TuY&z&JP2E}}c;XA9k3&F&cEMv%uKF@lhNMx{U@(3B1emD~gWL4R0t
zN3<(!E5JF=i^Q-Up}ISir;411xK&$N#;gOEo7U$Nrv%L<2n*p8Eb|Vq^vEenp;s&M?cOl5yhMhh@MGnvHdGpuGiQt
ztgh95#5JVM1Wga#dDi2B3n!DrsXr2st`&wm@JkbTWX;)032K%gt;j20hYc5!w-L;c)QN(;6zv
zej(2-S@RwK-3pm^;AS>?<1Llf9rhqU@~E^Nke*iBu5^==Hcw}O;A=Z|r_-ovV9i12
z(&~CTHus=M659({s9N!BP6eGzkiWscgls22#N)15+PANBb#`n$7T?ymSh&g4hqqKO
zdn8F3Tz=@Kq{>@00Xw@v3$sf(V8JU!g>r(`uzKjOZif_vG$5PirkN=;rm(G2CVp|9
z=ivoAkhG4k*x7f+D~2Lxq)&-RQNTKqSL1!Y%g5JJV
zzAL155B40u(`0`XWl3l#g6N3o8v<;LS9tr#LB8kL_g5rb9!OqNMaO!%wokoB!Cq*J
z7U%-RAn}DzUVljWlBC$oKn%hEAVhQWQ8!uT=V#>#Xvf?!t10
zCsw=A!+FdxTE;arr{M)BrAHX2SHjjF$b2pIN!1TP+b`3JLkBung)q-h=t#{W$&#$6
z=vb?J-T|`){OR`o1tTlXsS^hzuKr%+(vGHCUVUtPz9lCMY5mEe*Pn89P~`xwX>OyD
zyiq+iMZd-1N!{4=#NeM8?8P5;E~7P|j?W%;elfl5hj)OpHWT#pGTkyrl|OXbcXPXC
zygvs3?r1FtM^Yfae>UKAt-btP)*Tjt-XbH6-ptJx-Tofw8{
z`J#}NVJo)cbk6PAA>bK-P&h88f8tS`9K)N=^`S-eio6<4Xjumy;K4k*TJhvLE^ts`
z@Kcj4m|?vGb(|fEn_>9;sz2)#@J&D5C_lON09DY*DPhv@^zm=qg9@(jU=0>Mk(&
zH;D_5H2=XuY)J!tFh+9c1D%*qAz_e>Xp4?ovnJm&Pw1BS6pEL5xMJ1U9|imR)sk+m
zJ7r+kU6`_-mik5yNBfXQMl9#_V$Ghv0DFjnctaW#bO-1A%Y$gR4#HB<_;|>4q6-~x
z8D7_wnm0!N)68=386&8OB*l@#WF`>l$_RYFTa!JeKnd&Ql3b}xjM&K&6wu4KrY4+{
zeQ8r@PU){dmq
zX4APi;sykY4Jf^Q7RQmrA}jwwsr2nf&z~mNs^%u0nrKS_fS1?k)W4HFPWzK_L_yyZ
zJbzaaPw)#zUQWsO_Mj|x8Hn-xV0rcuYEzk~S0mv=pJum@)$-f3g
zAlMkC^3EvtT?(ikNMIs~@bLZ~sDn)8tu0(pDm_f`Vb2bk5`;@T!rOsyFz+B{q&;KL
zEHP_wD|`QhuF6Mdpv*BgYgVcaF%SKo`@1J^Re*6H*26#RG5RGxJdBJlS`t9Ub`V8(
zCq>>9EJ^N@aoQ93r@_b&cJC6UCt#G!2XzFgb(qORi?#AhM}@iBrII~|h1F7Dh$>YIQ5*rGcsbdPD{)K#HzCJv+-#$$
zru&D=zuYFg-Nv`x-NlI-IRtD=e8Ba|76AaUy54?J*Vb
zRA5IV$yXkGf1!m+n5-E@K9$Qf@Rr1(ivu=#qSP$gp;XuP)rYt^
zWlvk_dJRcxE`#MJB#Jxpy0|7NZNv0t<&GFOu!`o=r7Uj6i5#Y6iV&Ww7$kIs`Y@Dg
zVC%w21dC4K8yJ2w<^6sr>loONgeAkB4(E14TXc>6D&U_I-mBqufMrqb=6%YM4z4>W
zP2^fCfzw@0umXS%x3M-KPwN{DY!%LJvXJ(}7PqX2W{rI+S;ChZ=8jD)%gd&H9)iIm
zcrcm%;|XDKH(%+pP-5MPT(GkhPOOVdvc}xUke!A1gkml5@3u{3yBsadmqZ&BHFgvKyuCTDbM5?
zZKdGbP2JY@%rmd`1=-HpbROt(hxoArh^Y)>!y))*1QxXSV)Eqw;Jl9#i
z2hlPee(H@d3KjI&NQ8+A`#J30T^M=WJp(C5zLi89?ys_J%+nl7T&3Of#W$i#ObqP0{}jpt=d@dr!wOSgrG26E6IT
zpiB$*lE4LD63qGY*cb%aJ^n7znB?GhKA4idV(oGjfofg6uNa~|_?gLf@7AbT8)ixL
zZ~$CGngn!FncFnxHxqOvpn&ua}Inn`u%`mMRRg;a*r2KNR!<7
zNRuK>vpH%_afg+^>lgTiATenm(pOrjvnfWjRSw9UUS~EkCktHTH7ZLVJNFi&^-9Q+
z^bYyP=0Hux;hZRq;2w-O%pE%42FAC)ZU8N>v_|0fmDDt8dgiYlX{POhn?I&kD~g!?
zASWSs;0^4jl-8TFFtU_iEF^~F&*x2Jrm&@gRKL$lWXja}6LDlHn}O*8Tv4Jo6SvQ3
zb)d&Mv`X2lIe?-ppY2rmk%S=X+SYr
zH)#&`0LfAjHi!I)Fw2Tq8R!4{Z!#qO(awEwd*T+|Z$aY=MNnY
zu&X>kG&cU#f-iIC_A|KCY`-%q@3?BAW&~rvP1}g=>&15S2NTXM9{klg@&W#*zw_Xi
zgm$}51S3N1jCt@ozOxzB&2-&sYH*=;qx!gNT`q6k&LExssx8^tw>@FDKifae&GHoG
zot)|K#Wb$PBvC~aEqMFqVsPY9P1o(xV3{v-rMBUF`7g1<+SqB#K^*P?>lm?~B^+Gm
zmW=9~!FzT{&gR^QihP;cSp!&*j68lV-93(tgs)*82P>bvOkUzo9CIHxK?XR|5st!e
z2DEzE2}EZ_eoFt+r2h+fw!>2qrDYP
zm;Q?sG441F)ue90$HKZo@sQL(Pg-@O5pAqEEf9~6*D!4TmhU@0P`fde>8
zu-5f@79v4)0_Jk@6R*~Eh>r9Vna?^|-fp(M&k}V1kn~>40fv(1F1j;2Ua}b+xkJk~
z{_*a`b&fJcJVN8g@C0SrE)^u;W$zL#;mNy46?$m7I}`S$Lu^4;r!}7%ipPaSPfDdw
z09^)m#^!D^$UhlFBaVER1ay4LXY?@ZEM40JzL2@L;&DRHy#!fAU;j(=;{QjFDlN7i
zgfT6(0Sd8I><@?t$p5J)BkMteLH?^;Y^wUh`Sw#TYGI@W-~$t+$u>g40=hM!U2vDt
zyN$;QWC?WZ8;N+ylmk)mxFd*&n<5t3VlnZQesi+8;ZYg!5lkMAu~xD<*`zL{wg{~g
zmyjouQ%3}(VyMIuTM}>Qm$(?7%e?yTo}F`--1^3luP5M_@rNBA3jX`|y7P70`+OPl
z56>H-&+{z}Q$X){*h`Q85KzNXdp{6U)$OovOHkOAGk&|buS2jiKG^Bu!HKwf@6a8M
zD|4UAvK5|XvUMenZnyuX+ua7=I@uP~>+ah_FY1O-MD|
zZ9q5T+vVAdiMW@K8Ro&|A4K;m%!sikOo3-MVD$4?B9+53?hEq(c%-9y6h|_=Dl-xc
z9;(NCv=9&)51{h#QIpae>xqbmp(_q|@>CZa;iggxubX9h6;hW{BzdWfsG`!@deS-W
zSTxA#a@s=E4g_7)Z3v=VEUU9(M^aX|<A6;<1qQ4*BMhr+j`LrL5Q
zn2LsU6ksTAmzz45v?AH4)=knwyR`$W>`c?Z+>@3iJA3MkE_hW$yS)lkuVc>P%q*>{
zW#zHD+&H#h{1cMv$f~tP3;O+JIb#yyB`~D5>P^lDR`dq|W-b?r9T~NKkdqt1#IxBE
z>Vav`>`Up6;M7VLi;S*9>~ig+mb+61fXF{J&YjVb+C4AVgAh03#G*Fmn~`(3rMb8V$p%&KmWt*FXf>_mB(9)0+u#JqsHSlar;NjJ^oin?JH`Iqc_
z0~{38#8-;&{8G`3x6pj5pq(fBO#Hh9C3DBhA%G^2%NX7;h^~#*bYmob$CM1d!>Pzp
zr)45c1zneq+bAb9F>P^pP>%)OW|)H@lMD>D%wq^Ea`b6Df}!7#%92-2mB>#|7?gv$
zExmpaV4-pc%~!OiO`vdhCruy_qNwVdHJ`p@2=O7Q5d}hV$Oo@Vmqcs`fgo*Iw@u18*PiKs8>%_$~+H(7K}W
zVf>==q|zIg8?K6Tlnystz56a?|H|Aga$7u%zhwmG9b&ThRqScLvDXJ;V80pEXd2;kJ@V$3fiyw+J#Y4J;7G$`LGcSZw${21d;v;mGL%P){aa3ED
zt&|WtF5MmtG8$JY8WOzWXE&x(i%Ul=%R=4WViIr`@HxCZn&4DJituR5>@eyjjXONF
zrL}S|O*6&s3nKK$&=b9Wr$?!*No~LbxPQEx#SpQY|JY|%U8UAl-=M{z_2^#P=y2qS
zwdP9(7JU>Kg{PYoRyB49$zj-8UKdBRB_hMvH3WH>C2*A3K)PXZ9#dcIU7;#1k9UHJ
z2WkUOq!n(klA`zczTW&~q6r;yQbAkFV`Z-4_=oY)<%85pv8Z?2uLE0VqA#`q5_$ab
z1**8z>l-`k>plEMdRca2kYhmXi>?UwYloLnqdJZvm@g`d`?>#mi#+bVKLY@mp9yx!
zQuFJVir6Tg8pR_fxWa?Cl85$gNFt>O8fM|6$5@WjO|#Nl#M@DEh+g9bhr~WCZ9=o
zC@t09TQCMwnti}yYV91$S5fEV8*t`>+&K>&~MT*jT@(F*g62mnzsj(UK{5k%z3~)de#CfE1BH>9Y-*M^jkM7@KOWt$I
zI}7Bm$iuN+3?R{)pEagX?s_<$rOX-d&04iBY28lMZk@#uYs-CF23e}9O?%=1QpC?@@U=xNgM^}>S7a+cpxg+6A)z?jyGv&3?QBL75|0K~
z`pGSF56dqKyr+EWV0B2K@I8SDAc>4W+|(XWhk#*_As^8o^ZfbHj~4ji52T5Bp~(Uj
zPA@L;<5@aRy4X(g`T{GI(oTg_xRp{q5uAx|#G~VD;e=2faH%mPc3j_tEDouJ6UQ9PSQbiaOq
z?H$YR`jqDBUCojPzBtpQX5PMP;BtxIA46$lbn3>xV3is*FP&fHmetS%MQ#16Tw(Bg
zC=hE@OFgkmy##(+{-$ln&utMP&t?-(x@QZmB$1m;;hT;C`kVZ1UPs24L#P`Rh)YW6
zr6gd+Fc~w0Ffy-#1a3y+)t7|BZZcO4$8$7MliX^f(S}g`NgTH+X1duzvVDw3;LMah
zB)i0~T+NEHVr1@hh1yQnj%{n~~-Wv~Z
zfsCp|vJO_j&W^U=dOvQ8Rl|1!&$MBsE!FA!x?k(bs}-(Kztyne&Fis`s=f;S$G9Q(
zZ8q;PuW$pQ11G+_f5R=o6y@fJBcYX};Jttlv`c*CB(ci1@O})J<9mfnBPZH{4y})p
zLf2#nqEEHU3gmXOROOv8XGs!+&zwBLlva=KTZtH8YK^fWz1~n}*ha`>6)C0A;=5N|
zv#wFSd7heHfX2x>r?a%4AL%Dby>Wkv6MT|y6FSn!Th?NC%9
z;4c&9Jzr$p9Kg&CE$;h&x!yV1EJs6t0Rf>w{YNPeTm*ubmeUA@1c*_y{h?>j{8GVE
zZ8+74<_a}rb&15zH&k|E78ZgnEUA*=?Q0@Av$E=3)~By_T>1o$BwZzhucQ53Mhp)b
z9r)bWyMQu8SiE0*vLCZgvmdv8v~g1Gn@N8_Q@?(cw-o
z9v-bj4qCLgXy|OrVINB?e&yFq8ZZwU*)21L*mo{tgO69ALIk$|&f#{g%@^EDJx$F3
z)E#)M=RpPp-p|!H*e7#2gBG25v)@F4lAbQhA{a)bf~~Mx13FvMRgq*BYiYyHyIF({
z7}gj7I=i%vy<=m-EcbLL)vUXzmlmuHZZP
ziuDKQ+0pa5)(dJ*Frig?)!6pksLt?ml0)m2xJm$C<^#oqu<0p&1EbYb=4d6=7GaL3N->3uG;KO0en?R7?;Tmg(;|4pLv9;qnE~#
zu)x?g(~{>0=A}m11j03!8tad2_LT-^Va}xmwkoJ9)t4M{8UW8RNXV_(VCX
z^y4-n+$)Hg0ym3|z@=63LGcRnNAMERsJ!=y{1o14r$V+ZMt79|I@80N*j$xC$V
zK!u|vX4y$f8d=D>mU8!;EYqsZDe_b$8A&WbDkf<0NmsB+7WKP&ST2#Ub0R^X;N{&AMh~pPnL~cGWIOFsO%kDUP(vbcYb0-}9
z0Ex!rcPOe9>HP=dzpP#34R9Sj$(M~BS89!+g!>A??NSC0HdK$W
zOT7vCAm2dp3<%7hr1(P{;dV^{@Z!JR&(9?^Ss2^r;bR$iUsUA
z+;R&i$WW5^QzAt5Y)#8T@HZ(Ed{EO+~)Q*XY#zTyZ^mX$-b*31~7sBD|{llnB4K2lqU
zXOtq}LIYQT)@H^fGqNO4%ib`8G?wn!KbO4>cmLCmFjQ;$=u^t;uBf&5jL^&Xq$LBJ
z%QlL(P0rmkNL|BD(jg^L*o2-L42|w?)+T}9V1A=<8{%{E>)<;k
zFp*~FpvE5V4;?-y=izvcBGF)Dhh9V)Sxj*2`Swo0mK5`HggAF3e85e*o;Z{q$zT=2
zo;Jw`@rp;4zy0fzGu#?me`}v_M!l}Ukka?lwVYUcsdNCmk>1?7=sz!My=QATsnr*b
z4_gRg^AMAsN7Lh0+HEw2M0iY2Nh0^#pgE@_8WBf&ONl3p_=fiLEJPe|Kop*hx`u|x
z=CSaApSA`Y-6ZD2$)>gC@tvMtZi={Wc~cLltFO7)P)MisEdtgZ2`q*&u*wIN076uE$iV;lss9?M^-RK2FS;K>*d+qKQZG;Kp9OzCN#G`al8uW*kfn2p
z?V&>Vz>L|W$M>_C)PZrId5!82plm5opIRHo>TDiWp~oyh$MxqCc=+*G|~~PdFrNMq1wez+nye|Kfo(E#3(f
z5>TVAt%$0O_HBo`5gSw;NM~o0ib3`9n^u{IjHJ9CBCU1v92_DHn}wD9PV*DA=PsYo
z!iPx!OFp`H+~Y>B2ArDBBCGv%O1tMa+d1w1`|*$xC@EbNNmNA`OB5!QnWRJwtO%wM
zD{0UJ3>8_9Wy#b<)%_GZ^^jKAC#?+54q#X8R9lmUYpK}SleT~truGp!rgKtTr*D)d
zA4?&Zu(989UfPgqw0_>t9;&oL0~H#IzKw<$wdrXjcPPXKNjn?y}ER{wlA!rX9o^>m&ciV#UqMdK;xwpM{a_=C{p3z_JcUUNbMhRQ
z!aa&Z`Tk!(26uPD;yr57tU?o@NQcPvUA%<)lB;Uq__b}4m3`THWa6~CuqJ|BpFv`B
zehwL1+T3P-32w50UT!E$LpUVR5}h?Y=9j`SeX+WULsmg+sEgW`P+X*)o>4mQD|L~o
zgOex-&-2~X^@6ZLT)3V`%LU&CQzLX
z7OuZ-i}zZbl@iVg8QgyUp9jK_^}#Te{t5G#VLAagrqC<7v}f=cq8RFU!T#&7+n--8
zcZBBwsArEP26`6~-r}CA&|;W;mOvbL1Np9a@+^N%A#u5(Cdx+6E*WK)HM7Ls`vDZh
zP?@nz6wHtm#VbhZZVwCa#TnN#jYz%NdPq~7@YQjOX#=xk^dzDCA8_bJkY)3UozX)F
zz>E>1$M3V4w1KT(dcLynkhguS%%B!0?9_`runvTk^CFycjx+L{h@uE_LR12YA%=_zZ{qm83_~#c0XBZGJ6d%x-b;0Rr)eh
znNe;5z41nA=RkbaY3nkl{RO)51z9n+J?)5OOXa;Mq=
z8=2@+y)CZ7%z;Yfs*3?8Z^gB|(HaH4%vvoeU4~b~U#pxnxrCaw+B#$S^xuz`5W9fy
zXq^%61R9n}rYFRD7#7JW8=}mD+opz~ZDZHQX>8UA2sK(U3}(}Qhiw{RzMaUury*;I
z8VnOGYwECq?mefkX`J1fnwD0ZHuKgSf8yN(oEb}XHg?ld8#Pzv9i%m~UIxc}ZITE?
z%&CUy?MP9Ul}jUT>Q%Tj!6Sy*CNe!pZ6?)=|g7Sk@
zDsklg94ZXvLL=(PPOaDjf^h4m5LYorSW;!UL!7~f5bs=_#(RSwANcrWV()$H18v96
zIsMzza0h+P;%NGrIYp{9y?cOr59_aR
z><*Ygr92{jWIYgl9usurd`2W0GRiW6KwqNGI5(V4DB#aNQyf%vIG(vf$KbgrS_8gd
zfv3S!ZB1sO_8=2U#owZ6#uq-;&jt(Cb6?|%cfO*XnX!8SSo%8z;D7rW4}#qfzRSr;
z4_|GuxM;oS`=9#XAJIGINmc;yRBQ3TaZ<3Ir2VR*PjyLbz5+N6YF5KbOF1d#G*NYQe?mIZvYK
zZg94>aTH6vYdsU+YTE&Wf#v1nb?&<#&QD{6!w~c`)B;aw?zo!r=e&!-O_f)7piW*V
zxsG2_%kJWQ;}YJ0MZDzz;5iV>{wtEc7#jqV)d?F@Y+{UVa87VYW(<$MA;2QEr*Q(|
zRbgqG!+eSiN2vxW!>R*(@Uar?-h(!95!D_mSts78x&$xuC2;h)_0s20%f?Q_e$H-(
zXsAz=bz8pr!cuZho$~Uqhv=`Q&yJyfvj{Q)9i~Z+R~m%zweqlIfS&vI-A@g5FDJ{A
znIj{thPSQ7dMxprJ)MzCy>uUEyN$xYj;6kaK@LxIW2rS19!L)VT3@{n{9m}RXbVDy
zA8hNd^EuBgTe0cF{HdPEOveoVW_lQGF}uw6lB?BThF*@Onw?Q{Z-|^K1!dX&2N$AD
z46{D@CLJhk0IRIdEmm=S7rq@G&flR715`(pa&eKg`LtoxBqC4XBoRkPOO$nSCXn+A
z#<;}(d2KSrg^|LLUOurewbNz+8W)DGub>HHVLnL!014QGF@Xjh5YN`IN-O
z!d6}LF;*x1MEmqX36!dED1b0WD^qrQ>cIoWKNR2Wu1FRu`(W-AhYt6dBBLS$>_boF
zgDp&0(_6T4UBkt&aWayCKJ&c+-#->5P9J~~)_=gnXmrkz(m0d&+oChFCb4wi_?_C
z5!AI|N4#|5b?u$C95Q@15R-fyuFE@f5byHf;0?muU-XTh{FEww*|AQ8F%8C}YRrYx
zknBg177yZGp-;X<-mqZ8NAvTyoCA}E*|`2mVE{P3a6uquEE1R4CNt0R9y)-c^J1a{
zVcsj+jvK2we^gWW7Wps2KCeVCp3l7;n?rc2G28??9R7aE2l6*B+@!!nI$5KQloPHv
z&GcskQ(=t
zCZ8dS_nZQQg67Rh&|ehIKy?C2lo1`vev>8khdedNk$zyC9_UvIRkVPH
z@BfurY3k<_K>xFyiDCa=+mWB$3>NTzVz!z!p?%Pf(fFkN8l};ihR4kk;cVO-%rSy&Ynqp=bk9w7>oc~lQ3{)u3{B+#iSkfiFHUNuVqfwZj}f4^1Fl6A(|%AiVf{
zg08fz*KrR)gb5EILa4o<&yNBif}AK$Ge9Bbha<%+;1*UN)sQDxbZhKf#K;g&o^v?H@YA}hW+B`+5P0`
zs5>ylyvm`|dvI*SqjtvqNx3~*U?267)jL=0-9AooAK8H<5LZWQMHN-Zq>a?3dRbZB
z4l@`k{)*((8>!0D@xhLn+8YZ%wY_(jy>+#to3MR)h?K5fT*jP=j!9Z&S#`Lt$)#6d)lBh0h!D{LiSl@%b_6-L^oedx3v~
zLy(XyNliuSN(FpXMlt$sMUv?(0zG4wo@6f+BkICI#>(b^P4hcx=CZxj`56?x-R2VB
zGTU#K)dYHglU+tkb(Qp&*~=9O;*4iNpQq~S%+=&|jqQe3Z2V
zGU9K>qdFDD38O!zS33u4Swi>(uXT`N)art%H9
zHv{kOw+E-u|3v?cwdCly?Js82^?}azdOzC*(6)hW!+iS-!q8<6Un|dSF!S}0OtaEL
zTvI~>RPM|_#rqBKIl+1BR0np^KSBQ$6J;}KQ@>$;*X&s;%?>GmcRD5o|EpVLMfsk5
z@zdyc_6X%r!4B4SND8c)m*o^d=bd-a*&YNYgD%)}+mc8Y%OLZKyo+*@o=ONV4)-qy
zC@*=y8NywnJe+;`Z_@~Jf8uw|u{
zEO&j5TXGSE;-^lMq@Y?7kBg}Ry{^pwFnW`oN#k%McIv1!--nw#3T+SWl*V6#VVks4
zthc~sKBTBzQ%~XmTf;n~IV;5MV5~7#lOJuyW!0f6XlB@zNRzc!%+v1(G0PBzbb1=A
zut_PGa%qoCIO5DPU`mpc4_UTz<2y~!aoUhq6Rs2$6=%1(d63pO^fHN`USC`UEOHl}
z((`{cidc}Aq~tnd(Pws@RX}CrH~iu3pza~xkTqma?lrrwT^nXrE~lr)Zd+M9(a)v|
zTCaViK1N(O*x1X!%Kk09R~>(uayz!UvGNf;@R}!pJGL`_B&V`j%F9%WVC9C*HY*$d
zSxAwD!y5Wzx6nV6F@_G-8i=)PnFq-@8{
z?~W8Qs{^?Kq8?>$CH?qg!I#Pk{WpL!xkV^b=5JdZ7MYX7;*4ijq^0%&zlgM$q2IA+
z;s$P~X!d`p-$id#$C*`Gwou?zKjVwuQB7oLbT~NJxk&`a8SNN-Y+0AXi`S#Fd0eX~r(Op>2#x}IT&+l_ZUa}sgiC2LX79_%rTOeeW7S(oMF5=f>}ojEA-CKYZ)9*XQc!zaW#fPipB4!fpWP~`uoGoR
zyi*%;zbM4xKjyLB4k5nTiQ7kbiLN<6TYi7}A=mVaIM6q#mP&N}aLB$p(?r{qvx%YW;2oxQ{UW)ZK_8hkk+Br_
z#?vCrt@aQRr8409@%`kWOF9@~1BM|_=#7~Tf5OlbW80yC(P>Vd*J1L)i%h3>m|^P-
z54l7%LlyjxU4Ad{cLN1Tot}bWg8N?>m{+#`C8zE);Z04sj}>f7UC)gy{CIFUClqwa
zIuhBo^{hJs%$q=w0d<7^Xv%#v#sPPvecm$Su6bg)=6V3=DTSVf+?yTZKr>dE5G|R`
z?7;uW)j76j7IfP>w$rgXww-=r+qP|V{B&&Fw(WFm+qR7k`lRLJQ89VbwyZlj~&?>Oxg`eQ+c>vQrA;ypW9bSjT(?(O9Bk@%u}|WO!Ds>ZP{Ziq{4IB&v5FXLoy$
zGh_$pvUOJ@ITbSUXZiDTUj(86Bw}#Izhg
z+SUf0?nvs4!G%%_hmU27$o^t^CLnCljL++XZ1K>iv=-^Bx&6iv=4`*ayyw~whGW0m
z0SJ=LoDojV_t59-;^a|N@;|3^T!r8O1d@lqSBcuI;po}#cl*7EcZttvw?l$g(4(;n23F?Glrb?kQX(^}K&9+xd
zaeq2!C>2FQ!2DV^|FxZTe(KEIm1rgUs$8KNHT?O}Jb0Hd083a_c3-K@vv
z(-W_+U*@`B;ww{oG~qafb&15*t25Rd)p$<*r5PM*HkHf(#~;@w2Z&nU2cCac2)Y;h
zQm%ocPXz)MGd`-@_T#e>VLe#}5h3CTVF6IWf7(h484IuwMwL8bh*cMTdSk7n^e-Y~
zyhu*&vPtCg%6O}v+`l8{a2@lYK1Y|jPMrS5t|#C{0w|^&0XS`a?MLLfJgmA)T&O^|*Acnp?%3h6#QasA>v(XCMjG5DaQ#ajK2ti^7dU2F4(uFR
z*C}Jrlknd>#pLIzRXY&Yv1A%tXHxjoZ^!49wHL)Y)+$k}INM)UwW<)RaL2JGoA7`U
z0Hh-rM%1@oWSTwm_68;V_4=_dHr)s6g-RVnah?Rq5hoLgYa&&tzWEObm==oW3IjYG
zFr2q2F|Y|EiiWfdf8jmmVB=pkDmgjeEIyRKd2=Ia^kDRT!<4Lv|2C3BA;Kpsi@Dpa
z^9TGtC6Q}Y4cZO)b;&3I4+0|m-*YbhOBN`tFi=U}iYTWeq#K($wAbXEMnog6Of
zwKD_CX1W5-1S5E!dmviC=m+37wq2z
zL`M$0Pr2_Pzk|NRo;};fa}=4<7@OTadHueA?7q%=eVd;KtsIyIbD!NCQnE>|74>Jd
zFL;C;n2xGiq3FG)0Q#wMuFdHELee=Fp&c-|4phP40_=WBFuS}$x>yP-0$+Jobpvn?U)j-v
zkjt0~LVdY`+StX`VgY%gs@klG!LOg7t_q0A)KCV-$1mh2%`mh3@L*y&Ms
zLTK{N@B5;iWc#Lmoh19JofP}7f*#<|rub+x8Sc_U>tLSZ0@vY(y!gpC-I2&Qd66+U
zb&>K8K#d_(d^3&b-!!5jlv!o&v1Ezvzj61aD3RC7QBiFU(I#0BJVnq`iYF;-WYyEr
z)Q)aM*>$l9)ORh*Z{;b3yOb@47IMvye`=UTYI8IN471W~46Bk>56saOjmjthP01wN
zG)Aa-+G<`9GQ_#s$PmNFT0(Hfc)Jse9MKA!fd)eTFxeQak18rk&ceAKEj3YjPJ4}`
znB>}<*|$?X9kf5_CNa%>Py7DRQLeo~QEfjer(#Iz9;N|IJ1EY~);4D=9%LAH@o~jT
zwqa|0ywuJ3mY7v!*&(PF#;8TG!}m7iS~iLw0Oh!d#&gBa`01#-ZasucZLHxqm{G0*
zz?lWt_#*7R#15_&C{e8stqqEh^5Sp#NUFlb!7S4QxC<91sj^=dFKf?{y&*SJt2u#1
zr2;i6Xo(V_H;64;t>v|MuR1$v_En#w_ZS3@Tv3lXS3;)Ym4*tsx%2A*{#^h<5d~is
zd-_*HrR;f{J}xnVA5p2=^d>suBjPp-%(KQ_ETPTk8ZSah0&5oSMPSF=C+0_9=L;wo
z_iTJBTqt7;vh-tMO&+AQwo^P?m@P6vnJa~QYnxf8ei$1*9N4v;9f+O>Bbc0&)qGxn
zMB77}){wTGxYv6((h!$PLV+yK_P*_uj!PuGSAlDeiZu`IQzb1O5D9pCG6wb``f^ySMAw
z6rUKM3ut^J{ynxg*yELHu4!Mx$d9qH6?+?ow=C6q{uQGq$_i8SRk$YutZMQOJNFhZfXBdLGb@}euX_Sd>{l&>~|Qy8)r?e
z6qx+_4OkR1&~ycZUc!V)GMtr7&F9=gdfrOa^|iJB@RjkkfF(lAKv_7^+^VJ~E6Y<;
z#)?HN&>*QIDi|MoGtLf8e`*H)txm5kuWc{;Zh)uVv@nR-P9|0a$~{Ugz(Q;z0x#}{
zBrGw!5etr^%sr<5FA(B_NSf2D4tvw)RuAgh82b9z0G_XB1zPh^IMOGzS60S%AR^;d
z5u>H{vudJSHtpvH^C$1s;P8#3+MhtI0>>Zl{HKE@4$#IqPq90!dfu2h_j_{QdTG~z
zpr%`=nXg%`5vnboj-1WRts$d~Oi!Xi-GzJOG~Ii>T`%QWuE19LG~ipH4a@VMwVq7>
zvgS1&LicE#jruJ;qyGy>z#ERYc-l|*_7CH;j>=bFsBQJzU*SZhE5x~)rwc3vUQL9O
zc#?i~=NTL)84uBupuA>ckBOFpVBC%~vwE@Uu}?u`K1y?hMniCkNh&F6l~u}h%DJ6`
zk;9}zXryLj55UBv@6*!8fy?3#Ch_~F)^OUhJ;6xhp=lZ5hP2628gV8&e+I1y#zk!7
zpgpr#)+5u(+Q3+SQfxM7m`s~~b!=I2QngdCn$gLNuSX8hbkPfC?#ilZ#8fV!Q_O1?
z+icT)$HhJ^Ht9Db!Dl|Jf+=C8P){>S-9imLH>1O-H3fbv&7c*$86D*gR0X~E(S
z3jNbK@BY07FGb8dcg)}W&mVgIM5!O*X8dKl
z@?3?x(=QR>zpY;IvXyRsBFa14Of$VepYv7has%I$`|lC-44!^Fi1aJs<5GpHnk|GX
zaO#uw48rnC@jA-%N4STP@>K6ad`_;6xjE70u`7O`IV8i)thKVi~5LLb~90x9-XF)1{jFLXy~y8KUHfG#LcpHm9g>~juc&)$HXR1oO)ei-I{}`Cj{g_
z#OhO;;xur9CB<{2Jn>cy?81U2LBlRFiEO+!1hOTk0&h6}o`4#+(t+F&u$^{x<
zlWDt26wS)vu3^aLnC}i{%_22RcLA8*uMA6rQ>3#3CVYR&cK$W4G+$m@*h~i=GQ%gJ3L65(0c1b%KDWAz&nB#co0@Zzs5l_rd0szJ1a4g
zqi{1cf=Xa1tr{>HU)Btxtvp{4>iveP(nb(gqD5`^EVb12HIHpj1qx_Sd{$Mt7D3DT
zG;ZueYg$&Dl->lV;;}Nu8kz)TEDkDdb|o$s(zT$hrYZ6d{v)N7s8w1+IOwm#{QmX9
z^)nJ=m`l%}dopPM$Zl64H+wKLYwF7+)ajRHWec#z(K*JR$Uou<-Ql3yjxeB_{_)EI
zsv+WpTl8T=YT~@tAE;UWTWiuF5AnRkxc;|7jUTya0osS*UFvqZoFUZPa)kkF
zqkJw}uszpVs;MvzN4-L_0Zi(F$%js1DaRIKad^DnW-GGzI43ymvA~sS$mTKbvO!NO&*hK0t;VFDQt5IU7^o)HWt^d)|q5<7i7BN1j
zWmp)~I_U%izKxHL5nXJFcs$s&p^5jBKYpu1(GAQNgyC55~KWx4fp>jx)WQQ`EOsfhaxr
z>58FZ8{hlI-vJv`GqS#PUvQzxF#-kJ=ZB&~FRZ{F=wZwH|a;z~Wtr(z3q~
z=F|5zhPeb~lYG3x^d!zu9QCTV%gHl`?ppok7ZHZLLNgIf-`5K;it}wKQO-aC7%#=l
zeo*9HY9?RajwEExoo*}SQ_OW=h1tq4rq@Oy`CUu??A`{U+WDCII^cNBe64nJOr&{Z
zSD#&u&Tsu*P=5Uz9Gt6^^PH5+0AFv+kZ+wk;`DlnyUr}$TbzFn313%S$LHw%rv<-%W85yyFs$kT
z>MkwGE0+u>w6~=TJOYJVv|&VHiz8Wz2qn>uLcSutE&Bfi5^}Z+#fbncDe~1$_JS9Y
z%p06yC6d4ys>xqAX(Qe7@_0H0*Gq$xBuQx|NT}xzyo6=2SxNFBpIj74P#2rH5|Tw5
zB|5J3RIu22G*8$Ag_K(!3LDg9-xk`*ib^yl9l75x>5r6FOn{ApO(tUp_v8W7(?kuv
z)kgQJ4UDUH8c7YXtm6A5Bgc4-q}(wIIM^5+Rv5%J46|csDZx>#-E9X#y$Kz^Kg%1d3pHzmYphP
z!ma9DtF#V5m=9hV2p&bnl;+$@9(9R*3R-XdCFUdsu;6U?4ZFK!Q+Zf$heI&KPB1%W
zZIVrk
zR6u1CQ?UmqVf^205xmj>!9g0GawA9vMMD8~N1Ux1qbdREI+;NyI#Lw^=i+a3rQt~y
zO0$vDu!ovTQ-lPb)+@E~G+QByG~INi`hqIG>Z;y|`s%lc-pai#D&BZCWiLqG6(kJt
z-pF4CG7$V-p*Ke59h+bAR(bUm$5)Q)_@z%2;-e^Bf7ccAx7saUXWmW=jW6YLR~V!i%c&Nj*v5MB!(Ys(I^G?}Wv@=cf#V*pkWQ70TC!+Zb
z1CB2KP2Pn`!D!Z=lSGq?YCH4
zrNL8byH_GxxKeEgf+mNA3_CVKondx1Qeu=~;?K^=ve%Z8<<>TRZer{t=A2{j%V27s
z!;!VHrdf7uN+W(ytDJn@;xv4S)
zw)A$BZ?NwX`DkKrKg_x|JEY)t+=$cP+}nx_gO+lrBGT0vG?p5TddGss)1A}DiCqH^
zAGDfbiV62?c%~Ezj=+K_D%gVL)C`GF&rY!yL+xc;PV#Cug`Ia7maI{Ib%9F_RLQ#3
zY*E+nlxPG>%6gNslnme{M?8#{sywMp+!nHu3H%t=;v_a#R|_%MGi`S#jjF=(=ZzMP
zqY`ILaI(i*4l;jg-v|ki8)idAL4dnng~!Gtq_#P{&iWS98#Ak{&n{1$V_9u6;8@^z
zddg}Po231N?=6@_I|;}v4?w27mv0s@YR@E$D{&=51=ufK{tm7kJ
zW*^5v7aCLvcdj{daS3z3pINb^)gxhN1f}AJHLY(nc51a>PW7NjJCgE==fWJKMJ`@l
zpxqInE&SRkriKe%HL%!rMP|J&%5EClfZnQ>(6)JPU01nr9VwP`_?W-%YA4Pf^!as5
zFw8buTXe$5Mi*a5wDk{DwHri+q7O(((*bYHymlwFJJm4GVQINs0Z$#4`PHCiBu52u
zUNPUql_+A3mH*nr63
z;Qa)l?aisf--Pzz)oN?ZbY~em9w6>cNAah+BQsu6_J5&z4YRuWBy6g?HHT?28p8kh
z*uadAcJ|zjs{%$scZur^(rUjsRAWW+PD$@~G3GWyM>#owG|{hq2$#z4zYCtjLscCo
z8T%4p7CO%EN1OgEh{no{k{*P1q>xD*L>GvvE8tKbVkTI=6x!sD#{u`Tvy
z+odXAfS+^M>n!s53P(1RR+paw91J&iAjGyAJYEfl76;bm7gDzE-tBr&2Y7V#bn4;z
zEjwjkjZ#LAS7bW|zPVG@wuw7`I2k6}hi!b#y2v}0iM-EDDtL4c`I#m@mNb5ARE&12
z!nuaWHPF!MEi~*)12E%q$9Y|l2`rZ|Bn6m4wu0$0Y{$}bb0s|W{zx?xk5+g+X%3?4
zq0r$DOafxjZG@el#S+Ey(L=V^
zbz9Bz$NS?W^e+rRn4p+mKLGQa47J7rlOMSu0tRf9f3N{vg#@g=LLBC&pMMC#tW%X@
zwL115BJg;pr|ARB>=-;iZ-3)yyn6L?g&=sa{je$OLwEXUO1%HheaFjg*j>+Ob9xNP
z1PkXttf+JFyQ;NG(#4b5hicJi?St6>&#dtLB^>B@+k0u7)2f#_E7=)Ri@w`B{rWbG
zHiM61Uw%dh0$$snZVwCG>e1&&vz;H_HK{~(vcUQ)&EgK*KhdRI_QcK&wh=3BcWm?N
z{aFTChG+g)P4670(ANa%+)FM`tvD_|K8b~d;9zj-!VG-zfpQgh!(Q&@yZ1^5=9Eq5tP2614Z
zj9UFG3`S7eMfCt$$QP_ba>PC)15C0UxI@{fK&S?vPq?AJ8ZD*lzy2fCCcQ*>d-|jm
zIdu*M&W4#tF_onXzeE^wCm1KPzk5E!xR?eV#JOxBach>g3O~t=Xyb|i@V38SlVO}f
zoG}{_&m5o(2qNu15%UXAb$Wc-LD9Lg9r5C`csqFC_3}FmVF3qH;{Ss21J$=u64EPE;vv^n9+ie}
zZHUM)#z~g*hMa@Dr)4uT(r|CS_(Yv0*8L2G?##MD9G?5~sbyL(Q9Hhr2wV@(yI>OQ
zjQXryokXM`@Kt{XnqC>F`m4Wn4Xa~@9TbQ{e*SK=CMuhC80fO8sh)01XP
z3$?q^vvI^Gpw3b&PE|jetT{FSnmVqp4NR15lIbNz2+|}Stx}mu`0utVLGoXfWV?yf
zsO3B@lKNUJj8@wYh*^yWBi8*IY_LU;ehFoOuy}8B(z3NvTe_)!*t)s4+eoc9=%w@H
zqEf6%X>PL1YW0^(^!2y*DilFR%%biRpuM+8oReNkXXk!
z)%sLA&#zklN52ewAObBt5siFAhfZA$-+YWyTOTuT@TGiwzl(v)?A;mphgs$EzQ-%cd<
zNCEn@#Dv2)-GV*On0(i>IIl#}-oHBzMELyAf!M__h|tHEPg~{>V$Kp=#Pu2&x0KPl
zUgE(e!FT3}MSlb5^ou%Aa|?9GMSfPK-y?WH@O+c^_WO%%YfimM(Iy(ABSnJUrvdKY
zqv#BF)|xSHJCJ$Ib?JZOHrqAa1~7S>l_fxK@3_PJPZjU0AIBVmfutb+1+ya<>#2G9
zFA(zNW#{D}fM_q0(bs>UPcjIu%Ct5m{Vy0dFyWs{6aJ~x=}V=Tl>b!f_fMt6|5VEJ
zKUJ!@hmhr=dW^TYNy3>kE*b^k^$?D0l3i69^qM?vXi=s8#T~2{qUWBIE*3^-0PYY&*HMq#zy<$$C!BhHPMz@*CjAt*rW<^Gq1XJ+5`!+)4ALQd88)e=3y?sww+YDdm5u6#Rdyv^gq1km-n=ZbuFz0_}=~
zlsLi*p`ZSNJaVV_zf{^WlOhDZ+3FUY29Ls0sq>=Xp|r6Zewj&qS)cDP9$tK`^nk(N
zdBU{VTxbU;HVs-JFVmzJS*~Y<_N7zrFP)mHHbHc|_~S=p$)^~Bf(rqo5tSmtK+8_M
za!Uln(TH}xu77X2{GSoQx?65MkmX1JIvl)hk`LdZ>I^dt+H-N)w>&g!Nv`y
zhw?i@Z2w>ZxF+(SQ+*64e&QaM21L8jqiVa+Uk7w)3hH05A1Pn3A&jER|3Rxf>qb;#
zBS`*jkno3Aw5a9Sl8QzcQDMmIrc@E*b`AeOTD8r5J2>EO){+dDNWNlbK9%Ww^ftxq
zY}T?52A%>6EXK)_n}r0r&rUgkoNF15Y)05+7%`k;*ar0Cq4Ulea*?^Dp2aOYT+CDj@
zFBZD4sNy8AtBXwBs+q5zc@|r>8;cG8i-o3i@6H2i%7ol>i}pMt@m=>a|Ha_F{*T#aqQe!`2
zvkd%6mHh(umpDCIm`Btp9*H{^VkTx63d9fmCrEiK`qyH<@CcL>w9vM+Y2im6^=(uf
z44A?!dk6i`)%@2g3Ti1O3KCo&6eQ&m5}XKFfPYPa3fGwI=N8}Pb-n8RwAHn`4eb64
z!W2P{sz@dp$jo2_mariOD-jWD5dOOuasnpR)MC^s_=t|V@~a!a%g&rLEy$$dN;XSm
ztv0vjFIwSfLvmp^$Mq^dELAIpde3jyCYxTN5T-IuRtawIG%L-1YtmU5oloP$(A)+l
z(nn4En2)S3*?>AD=ra6x?yjGJqqZoY{LagYusC*FZ+m|#q{sa83rZ`tvS_57cc4>l
zQJ!Ajvb9JGuhy#Lp{rX(5H{eSY;j=VCrmTKev!|{XYui@%V8A0J}pF|`HLpaNijh&
z#Y&HwQo0Jc=-ByK=iZ>gYJ80Y!QTU9+W0m-qvc?7*x#;m%ektnmem0H!$70$*Hhbr
z6}1G7*34M&g$jMVhqG$8&4>Tw@OiaWciZRJp_G6Abtc)?R7AgPxE*GrmaFw6O*PaW!rQ7c+RP1*
zt1FWBw%Fm-N*gn_^D~tXU&$2gQSMo4ZYEL0v7Ad7!O8yRwA1B3$Opa2li2PWF%UH8
zmdKP3e_K!e>MGL$yJBkm(YNu|$3{a|eP?qFc%0V2%mI$Fygae!+^bXpSbArkW74@z
z;tebF)^OTC861A!m5h`eTOYvxmAgL
zNN=rLR|JHPr}rpcUNLhv%d=3C)znmcwYK7hioQn}xmQSG@6WF*!RLr_MMa&6XpN}+
zl^N=#f#OIMfdEd}M`B09@HK}6fi-0yj&k51o&f&d61ryL%bk!3W)m()VnLIW
z7*d2!*g1?|jG59{RiR(q0#s?Z1aAmWVK)3mF7_l4?~0A_SuV^L!X^EvLRjq{nUxhM
ze$#cHv*Ok@arA_P)yk2##O0@5#gyVdOS*fW!4*Hb0{`*`_CQ0tLsK3YM|-Dq97uHI
zaWVlVZi%74@+{`LSox|0_et*A;|$JF{9;UA&ZvHzQw4}8_TnDWL-XQmleDilWtMy`
zfL)Wbe{mK(lBXP_^gI_zXoCD`$0#t+TM!G5oGGYhe86I+GxzmV!lH^4+(j9WhzQ;T
z`1}9>@$=<7)PHW|iXZSu%~_BjAY@1&Al(1gONjU1Xl9kVw)z*E`AGqu#)JTtx1c0l
zk+dWr4PMmPET|>n9}E>9s3%nADna3L!X#`?p>fueMgIY-MK}^))ZP9L+V1`H
zwQ~IVj4wfe(xoHO!GhNk)drQAy;7
z94r?>4-f~{QYM@$LRTn2&;|5szbjABgAsVftS(wN>=z)!o^l}0Vx|-
z!e%I58A?T*K0pvvx19g4<#}^6lji7ZC#O6SdT*eS
z@OXNYYltGsJ4fWG7)GuH9x&=2IZ~Y(j5bOZlJIwuoY%tio9>t2uG}tUIMoHPU6&pR
z^wZcg3GW~Ii@I*%>lRKoAvifAaQ5;V_MoBDGmmd2eS*5$KC&xxIAsTJ;r#089$FUW
z!ZH;vEy(e$?Z{RYo>FzZ_+tfEdE0a0sg+ahoNjLRy7l(CtljF_c}MuNgiA#
zTgdGv^GW%VZt*4KyysY>unc^%PU0c+Ov4u!x!HbB9WeY%7gZ=Jn}Mvu0G=^S
zOSogILjovwJvw_bJ2mnWKCH7$R3ilIF|wEY^Xe`-Gs`W}^o(rulW*YkOl|ZlZXUoF
zxW<)9%ojV!cU^Ug{Atcf(>o0gE^k^{s&LzXacY!rnM`e$&v-CCk_^AnZLY{=oC)`=
zqiyx7!d~z3x;?xNT$^!!mqSX;lUG5|xXb@u6ng94Zs
ztvwD!qVG`CZJx1z;O7&kaGPe7^AWsa@e`WYA}vcKW;yPWbPgIHh#*ep0_nFhv-fIA
z6D7#jx+oIBNuByJV(;;tB8|ZvWy;hy(%ia+QsaK&Dmqgg$*IiBs6f$9DO)12!0ocL
zD?w-*s$14(pBQOK7oxYDj(Y}2LH&_P+nH(0Ya8C(fNHZpaKThl*4!F4Nzk&Wi_Ds)
zTmC5MLvAaE>@tsHKxRii24*}K
zv%@0&5Vj6U8h%)F%z&67gPUDu*cn#i@ar)ovg8Ytyw)oC+41mE_}uycUijSp@FrQJ
z*itTja=$t}gs1su6s@vOC8y(pOp(1d0iU4G4iETKRCpVGdo|
zj`VlA(do(@7Ux+=&5JmsGgeh^1iCA>6YGwcv2Yqbt>>mn;tG?j=;}pkuT>TW|3ZBn
zrZ9jVGSnNiNjesDS6@t*$9=fG%onxWl&vrz3KHT~?0qHlH@t;bU$LkPeE~PYhE7jb
z#*9*ruJlTC=$UC_F)&~qe#MdCC*y9m=*{>_8pF;Oc_YC!jCY8xWwukcRD*Z%++t#d
z%9^}~L=j{-vue-PJOSiJ3ruvE@>WIO53#SD&i{T$hfWdb
z_=no_zKy2ZplYq
zu|l=CXpyE>O%Qu8n%1sqsmQ9r&9P!_ZSB#%>5>1q`-i=ro|%NwosaWzwfXi{R_FV+
zcn-ub?!A=LnJ82{&$iWpNi(}h!F9?yoKd2zoSU|h7nLAMrV+L2+4Gtd4o
z1xwb2!PnX6b~~rdv&-4BQTUS^>+k7!gvBi~0|0A!{>B>%5Q$aT8^O?u$mr5*(HUya
zAQzy{-Z}8PkR$lncB9l8iNzovu&m<_sW%!>F}LH2*y8wn#^&A+DZbB+t9K5@nGNh8
z@X3*EkIp!6dj;j>bZ|Ci0NL8>)4t^({EW>YD%!tvhko{*n9Rc6I`n^SO#r=|yRrN1
z9u9im^V!(Q@k8E`ci;c$y!rl2xM#*Gyx9-tk=k-`IQiBZ=G3qq
zePQL3jeqsvkqjT$>*dsCBAlMRq5t&F$k2DVkA~kKe8xU!Y{w;$U#
z|Bz^xI1;7#z#UU)*ig!WW>_ra+3cs{(mzSp;UYnNdV!Z0{PGNoJSTcJBj
z1;O8KmxP8u49#@4YdbC)qjNcT)|Hkp5k!Opfvp#TMb?X-BzPN6V3j~QPIoZ9z&h6w
z4-OBW=ER_N3;DF|2KE&^>V5XLa_UeK*T1&o0hgV8`E|{CdDUjZK7(tBQ5cI&6&WbC
zxWo-K*f8P%KZ%CnZD|QM`(HSAC5x_P3DE|nlO0A0oFXeIPKcgX;HdVclqa06IoSQj
zurKYrsQOF_W}5=7;%dNUx+)Fb7AxWTa!iuE^6LDs+T$_j0kPbMN@}z_NFGb;=DpTg
z>4C4f6jA0I+g*pWvRI6&5|4EfDSGWw1J8sS)}642;Lwm)VXpca|1K8nLVCYDQ3y&_
zv0o*d%hGU}oH82YULD$9#IQ8QT}6ESWu~LCplRjjw=ZCo23A1wo<=*CT2*bY(7|G2
zLA>-q$&Mr#qq&-=pd?iMB$ODmRMB@!-rm|6*BA$v3kh0V*p$aoSyOP8W-AH2kO|1w
z43oaL8LS&oOk%F^5)RTrl{jz|YuD~y%L-F8W`389D@V7SUP63?6{Cp~DKU+F9!!OS
z<}Qw4;>M9lVVJ<+en@b~2Zt9bf+^;}^8Q}BDgmiV?V&o$ex6VifXzXFlA@aS$a$E1
z)aqi>H_!ep2~|2IGY(OJE#5gVuT;}2Gdlav$g@k!l6$KS1FhPMc`!4T+l4^TB*(=8
zBU7nc9*Pl52>I}Qh~5#XsaQBNoT^@h4$j7*Wx~_^(ZWvu3kHPvc{x*
z)EboFg-I*>l;!1B3}Q;_XIGbnH!$n{&18+`22tyA`K1F
z?cAN~L~JwEE-1LOLlkZN>vMoMEk;;^Z8+jj56@21Z+X_Ie>yjytH?nxrly8i5$@p
zPmF2a`5MpyF>`1gLn+UD5H+6M1O0JnC5vunq)-JMaMuKEc;=N7fyjlS876HnqYH0g
z(~9X-g69lh{|I1;x(UL&)cmQ!FFAxphM^B*Y(ve1SxS93ta~^!+U_lZmr!)F!A0r#
z6?S&@J7e(&OD`bJ!yG@@DXi0%t^y!uN&#D-FN<>gv$uA&Rt1`S7xY^s4Pk4N<_H0o
zY%e2l%1_ZCvH_aL`c=cA%{k9|}uSI-#;QD*bkF6q!lB%vO+JJ;pe}o)lWi
zaG}&=EOch~tAN3eO*Lj$&fHxTHgRuVR2Ey2x{Tc0rQ8Yy;5-kz6JR>GugGL(P)oMr
zXcTC^Qy`@(iB*n23?~?@#-7F$884~5zdw8t5fPv>T~Ub`(zA|F;rkbeYVsV&j_0+s
zQf^J<4y{{ww<=yFgz+YHDi31bpDc1ljn=2XMuXG_H9+X-Bund@o=L*&$O`tYE%-AF
z-m|Zk+~nifBfb$t)cTfsN+nYnHM(;uehuZcFn(Qj(5G2k6)Yp!Fm+t;dqaW4a0CY?
zIL&SdR}%`y2~|jp_;HGS;es^yfU@TA9@C3}MsWY6%AKd_DUY2aFT
z;%vmIGPJiySRh8om+afI@(`
zv4&w-it56)qH(*j$gE^14ljq#jIvY9!d}}ozK^-q#m30WMlVtTbn(S4U`aPSH^cgC
zL3_mLJ0b1Qxd^uwZ@F{|jS(3Zca?Gb%x{Q`AcW9i#f7p7;evE~pB$Q%>85&>>)Go>
zurTtK&{f+@G1=QS;Pg-T++ToF=;JPmv~n|pVfk`ck2e^m4TeJ!W+rV&J~uEPmL#*I
zrP2gTx<)%yT4*LKZJO>cOJ*qZ`I6R?cd@l
z%Mcyut&4+cdvv;)^i#8gZF>OO%$f-JfuQzQn0XgRX3i9tax_Y$d`w*(8ix77!wntc
zYO*5zqA=U`*7QQ!>bS3=a#nk9?X7Y;Ii$V<{di6eRSb6DI8Ti_R`Mb;1|QkHBBG@o
z@)_(fT2A*u5H7_Ra)u$t>U(Xd2o$tvxVy!OAof#BIYZfZt_a<|Pb6%nSJl`X9
ztf9D?AN&B^gK+YrKA-Igx-Evd)M;Prj^`Kp#kXy7YB{^9CZQ2*$a+r#&jk#@?m0dk|nM-X~kpwviP}w9D0Jpu;e4mN7OIA
zenBwZBD>Hi)0na>VEjnB&nvxal=lHlY8XnVI^ww1BfBveXJQ53#tFJiFv4B+U4H3=?~OlM2?tZ3PX8reao4+4N;6JNL<7mrX@)i;4~Yin!t
zEw4ik+8)ghxR6zVmXk(iO~%><8YA4NpM0lGt`BH@Q_ZG3lNL{8`hY}2Q{8^ywFZX7
z0~X?;RDWbs%dp(7^aP4QLw5b^)Uow?D+!8o2%9hKU8AeVK7(w$8C$)qm%Oy_xsIFje%o9OZUrTwLYG!fJ?k+cD1XuFC89FnSQvvnrd*>50MUzZjetrI#h}-nq
zK=nZ+1Z~;UclBt9lwkh}ah~3a#OYC$z_lEoM0{Z6;~iO&{so(GIbv*W-^X4k4p~&w
z9mFoH+n6MZ8l)Fhv{e2|s1-P()J~W{`t|y%ORikJ@fzV|DYO%XO`7NPRGmOF|5_=u
z+bdc&29{P=h&&IV%Fs8i<_OEKsfPTCY`W&4T-@0?BAw%n#8&q)JDY^1mBiFRlsSM_
zDier!s^+Rh|Jx&E%?Gr2NDg1LHO+7E?3~WDr)(q~%2TZ17?IyZ0m4Sp
zyiR5yDxmKZLS6LbYAQSg_E>y<>cI4L06^@G!1E#YA&2BxPCBBdc_BSuEYY51k5~JvnQ9Gv4?L2`B48^WTCxOl%D)s_%C3^CCS9-4o2YIEU`US3^sS($zyho0>LgKrKQWE8brt(cIB4F92i77*a)
zHnk8D95+fAn>@O2)4ci(uS)sgXPAO?JrbzI=bm}(vWBv{vfw*&S&d?~CA$^QBO}5=
z)OjR=!IHV^ow|P$thx5yVIrN{5yG3GEbOJZPU1tnJkbx8uvOm@qwh7tWpNk^C&1jJ
zS|In_C_0T%6J=0{-(zW;l_V3a8gTWMBom({s)hf4n29F2GQ;zrut>&cO-fXX6L#Ut
zYf*q;`RZ?qsNx}7`g!Ns{#wM=%NDdkNcalg>|I&TA*{~dGBiBEm}8DuJ=p*4A#XD{
zA|J!A=F4jZQW{lH2&AhPR*zwf9rc_HCAubRz1%v*#uS+l02T{WNODgsq75>nkE*4-357z
z*Wy?lm_cU&PB1zHiyPq|J>c@S0YC=%=d6IoNrN(UwVKEKCx!lic6HcusRa=l{{el-
z7IZ=$9wwLoX5kGj(WBA}vAi!olKjjwmpfWE7{upqDNxWq0L1B$&xW%%Zuji&;XZhW
znT?GyNyj@idw%pW{9Sw6XawtjJv6WI5z9|7MP4NxDq{eG7D
z#F$~u@XWPb4e`cyL+iW|8@Ft{O26{w_^)A({Bpga-7>uhdfo;9W5z{9!?g$@F2O}E
zx!Z`A`MAi~K7HEYzYx>izsUP$AgUwr_UX
zT5yVdtP2hmgix=GMsp&=Jp-gqnnE9a-r-3z&FEV0qwQH_F*V3DYmuJW&9_9X$ThbH
zq6Fb*eoC)I{qNY}HphO<7i%68gy?5M)vsMS6!7cKyEg{HgtD=-C6;bAypJ%0FfM-}
zJQkrPM#zh_XzULO#DrrVBpoDX*U+79s*Qihu0#8ptmnV11A
z&gf=MGPz8%?MaCQ0Y5>MlFyw)4I_EU;Rc%?yVj`iN8erl-~*q7n
zj`++sY)haCo4|KevIEeF{-q)_B%9vNLN6|E(j}sv7&`@2AoO)1{LR&VL
zpl081T3ODap+1VSu4BQWk-9IvKwzClnc<@9a!g^^FRtkK*_bo#=Br_^Z@O+W$)R5&`~0P!%3+iX0w1&YU409^
z{^j0x^{qQ#el0NzBaKp&^g-~{%bfJ+-z_t?Lgi`)QP8q0ZriG%s?Y=|_GB;kR)p{%
z1I~=O^_x?&(N8?W0C_DAXkGgXWDiL0XX@t(s&w_}Z`sD@mJ*sMtP
zI%Lmj6-9q~K$%_!pf9IVTRkc+bfnkZXQ1!v<@3D*1g1xT(kuNN9Q@W-I7GOG`-E8O
zw`qvy;lF;xoC%(_WqL)ufsnNge#I@m4etTl(WkK;^#tk>@afYjZM80*_{5mIO?oqp
z?~8VdAqeRq$36_>d&GLMq?e!;)f=_VSYt%p^9Vb$d9;S$@%=;If%+dxmLH%v2|Mn>
z_!bAaSxosYc6};MLMH7}^gN-vu4FV3e8{!a<%(}7MDile3^M%jkfF6k_eH>33d_yT{1%xi!)o=sc?mK#DQ4_%yCc@mVGYAPq#Qi<5f
zLn=LyN^~dh%YS-t5f$BKl0ziKODAO7hNC)Q3|DBcxUKJwk($QUH2WwGenBxZpT@0W
zt3+LTgStdRl@rOfFqwUSiF3-f0sd>|iH;!4I(#zcy4fBdxr3!7C+v(AoFYe_XAOtez(DG%9Ve>1VW0F&9PAJqAkw8&96x)9L&XgE;98aawwW*S4M+``8lW5oU
zGH>;G43W>`hZ!5PMAjDXz^JfD7__KDKI$lAgoY1`iU(4cH`8F)mD64Ng;`(YQ~CzR
z(eV}Zvw)rS)q?J7NhVm0%BqjxXaPFI_$lc6e{}KUm?@-&l0f+GsC1+&8%S))nR{x6?V@&HYM9`XmLq-(DBGZ#
z22zh8%$%{JsRXtK!9dv_^xmopq^mY%%s8SmY>FjVZX-?Mx5BLIO<`N0R|5aaszdJ-
z<^ClJ6B8(`&1)fe#D=)X_Kdeh_{4{sqQiC=|H!pv(~@3&3*(k!;T9^GQWnY4=m6m^
zZN#b!?cosF&`5Jw6y4V1wV;(kk6?n*=!R&)N}7V?W;mPq5a$mZq2dUN5r6k~o#7Bq
z+54^X7m+u!!B2YMM^!hkI2M=%jZko&JK)0_`7
z^bh!0ueyDY6MO~6J3=pWj-ZTS#TMab0)wpv>Ip<#=7^}tLVt*35}&jfy;u<53+e>;
znIGQb(wAnDwLfAsQ?jxtpY@&N5+#gSjLwHm$q+QY5(M^x
zljK{pkUT}o>v(hHk}VjNSVVRh1$?$FYqo5*fiZ}sB02_&ex%>lj`k+QPsCa4(*i-H%tng+W`FPaojM4gs$uLcb*j`GSbTy#=xj$n!+3;E!(UHM@F~wfSSVLF{s?&)+pV!IZPDKN
zL1Ac2;UU-^K>&6KCv0!nw(;;4+H8h`Dq94F-A=Y_IDWM#x|eLE^{>WB;k_fTYXuWJ
z(=H6nlq~|n>VU8i^E$G6PQ!$g&Vk_`H>JSDnDd&ZEB&m
zQKSn~v{hQEH@_?+?6vDAI-iVqY2H6LPCb|4&;~`ic0kql6?se8Cs-FFFkb5Vu#1R%
zCuIr2lRwR1EV`gMbG4&Ty-G$tF*C>ma4fM<-v+pvMS7aj46`A{f1Zg(ZWXzbC%LIj
zn&K6V@sme&wZEf9bob%Q&?i~L@vM$jEH8;dMh^YCp6vwF1sNc`xKMzdAc9LBx2~1j
z7TXqZ?+5rIVo&dUz{o(X>?**zas&||47Nt9H6=@>Txc2;$NeA<$iB%!@dKJapA{@6sPmhSQ>+J7NHE|N0pG=ikhKzKLSF9bG7W-=
z3$#{+MhZu@cwFtGYdC>zS5~lCin;p7QP-QXlmKk~<9{UMK9g}-%KR6HFM!BN!IjQZ
z*Zbk0e7>&~+q;g9Ei5W;&y|c)%kNCiBOAFuy4!nPlRcTegr2Lwg%H(Cu(fH$_AD=>
zxn+11*zTB>uCVz^1bvZxc@zt_B(?dPggzDECZJpF(67Do{h9-PORh`oC$0@N^hH*d2Qe*QPk(tps^L^Z=WJy;+h{v1hL
zsb6)p@YXM5*7#3YkNEleABPh+gNTLwCdGGTbdMM(~RmX)*t(|R*kH%w5_yT+qBAVJ`TM$O(^1|eBawQ
zU-=VXGu$t^4>R2_mM=1@Ivvg+Q0bKxU5EPjp&0L?zZ`##BfDZyjER@rGjuU#C9lVw
z(I2GkrZefZbx$gj;R*_DnL2i}6bkSqIotKW+*
zV+u7=v)PC(UPOOk$=q(}kZhc9^YfWsnG&oJ@osb_$v6bCX&j*4&exm^9qW;ebJ%+#G__Q0zg7{tjJ6lP2oCp*hk0JGTb;+u7ri*(aws4-X?(s!h+G2AuYdhE
zFLMMKCi_na$H<`pO^CL65!1IA#}BH_gYDI4Lv63{9I+(n$BiT
z-j{T?!%5<=r>O(0ip{(Hrgv4_Al4a;ZDb&LcV&WX%6yIi*$KROyZ
zxDnS0JjAH<6}UyGSbH`d)(f^fBNoIc~RWuv&FQA
z87eN)t|l;a5?c4_Ml=*2<15Win!}NwT^c*
zCDWXjBLJ^SE?jA5kB(t$Xs;dw@DK?(@z*t0cQ%d_+FaL%$Tr^-({=P?AxUl$IEuG|
zqZYc}pXY4cWMmKnO#g~>CW!D)LgH;Tos}GTvkA1_Cmu2dH;dQBT0A{JZYTiWiE5ck
zhP(>eZ4lN~k8MfeP3z;7;cqx*6Kw8eD%ycJsHePco|*y`#o{06yR!HIcn3jnz^o=2
z;bx|ox^4BmHl5W|J#%+qG6hzIjtQx1y>h%+-Js%)vVj5oN+7O>XTu7gF02lGXs8Mb
z@k9@Y_o7kO?3qa&`T_M5;sa=!ciB#10=0?&Gp~$mb0SR0K)8zSWt4Z9GA>_uNtwBD
z`vA(y8&mB~hh6a`VI&fexaj{8&-*{ov%hZ$$@g_$ItHnLh2P!Fg)p=
zw3leucNCM2_|eh*gXu_(?1vu^Olpqg2h39EeR?%6lbPboFzcIJO-4&Vk1Ja*r@(>{DHd3QI@+(HjhQ8VbL}dV
za>2NwURz=#G6YqF}{j?R5k1Ow{Dh9FGyZIydFcWI%`wL+pR#d@{z8s_k2+ObVjbHOd
zxw~9|F+P98FD!lXi2|^Vn;T#VtlrO4FNil1&3D-D)9NGQ1$m!_Nm`4z=Ll^ctKg5&>_ml}8<+&Wtxk}oYu3<$A^v%o
zGGT|loFVWU=NGeo$m;_NY{U+&b$1l}B9lFW12l7TZs7zHHiVBuvOJPmoX4;hNK&k#
zL2^7K<4QbZjsq^_>||Sqay;@1sdwlZOwW{WU^Kud?MfR0&6qPY*bRmANEN(?P1@Vw9
z+n62{kNp-g-M6bQsZoo}p-7?8*eBMK1)@h}Uzj7s_u*f`1YjxR9OlpsmCb3Y&PZhB
z*yq{)2Idr|eR&crN`G25lpGW{Uj;Ff{)|k8Zaz3HW|jM!NCT#mo+k~#zR=&tZ$n}SO0J_HcQ7G|6>~7x~>PR&jc)Gm4Iyu@XWFU*F&tQ}3n-fI^$@q$&w!)DDyh<1kRw^_1ygv4(_OjI?Hh-z`?}E}izJsDy
zRjvdMBrYf+W8^7yTie@v>H|R#C~`lawOO;5mE)y5#4R-BoAxw+iy4ZEtt!t%$x`96
ze-jM}F}FEkp^eNfVcDb3<(-=K0mIyKJ}l0+rRAaZZW)w3<2l)1g=?lWxXej9Siuec4bn$}&B*3+*!s(c
zcRv(Yny@l2W@ly~IRDM67zJXNGGf>L9#K-&3Boj9`L2S0e3S$1@vLL!GvmVq{N1qA
zSg@`5ZB1}*li^>yN&G%d5A(Y)`Y2xY5~CsIA#XrZi*;XZ
zdA&jgt#E&Ly*W&U4&D7ddLBxA@L|ptqKv}L9NU)sRH$_t=}IM*uq#NPuQ00B`bkhu
zW&fGi(o);9OxqH$LaQk1(?s3-?=wQBnih%u=uu_#ifXVgoV39&LWm>W5L(-hsPTXYn92BmMlEoiRKQH{ChLCBvBaTEbBD=DRwva&4gqK1>Obrmele
z_x2pnPf0)@3y43e~3?3L8l0NhL$g&~*G;Ui|T
z8J+Xe6;rL}ug!0=Iofe5Y&`Oraen&D34uM5Q;ji6fU$u~>eGp;v;uy>C_4wxMlj;7
zrEuf+FDw{>8Wra5SN)s$mLH2gq4H@!Us&yhV?zaA8lK9eTM$6t~WoNo}
zz5~e2JP@4goKaltK~S*z;e?Ba7iFeG&>Tz^S2%Ncglgo5&M)>HPaDK;+Kgz=>
z`v(Vv1z=*@QL`q|3MGux-*biE9*yizP~^Z}pt_DhWHO0Jt%A*loP*5{CTge(+|$h(
zd9rf3Dsw=>C_ZW@U2f#yD^)HHzA
z-y!?)3i)m;0qI}hzkD2mM|NNJgG&M;iM7Z!J+$~lWp?6Zn49JZAo8aJDU%G%m#_9}
zhpu~f<5!0p
z-F^mFw3wn`6<9nI=BX;Bg1B%~@7xA}AdH^1yJhtLUK3IM*4xmc7NYB2|Fly(f%9$L
z+M#-2l95~d6qZBVIh{i=9$vkvjlrsP<5YNct6zXK(IsQhJZ_8qWE$QONiNYu4@>lx
z$GS4gYW4$dCF@I+{&z1QZln;yEvN(YwItv#lPU29;
zKGl(mxbw0s)Mj=kv@Se6B5{jonAWb#$hafO6id4DXo<&)jY?9%(@=uujLvFQro7Cy
z*^mN_oRRPFak^fg>qSZwwU{}g&3$p=kPXr0$t$-|t@))Go8
zqi9jCpH{QPI#*L_(b5%PEKUQCnpzSvRgruDbcSbCG~j=$@q}#Gs}Jpv)+aTiyv(cW
zO~6opqxS@l20!(T=ztx9jVwFXzO#nFB9CfHOjC*GvvY*-5zb?3pE}|xYbu*kTf;tyBLP~HCzB1&m>VnYp42E&<&WC<`jQd)S{dt$IJK~!qGO(@B-To(ha~ZiA8eP7UtZNypL^+
zI%S7p9#Ec}+W%&huqXq3kwzcl;t25)`;^a}??MavyY!S6m?g(`t)?cKui<$ts#GJZ
zh(fFAJm`+2y`sB@O&yHfsL8KqOm+@c&^}qnuWL+pu)bC_md_Vng)h
zh0bCKHM}8>5+e0@o=gvA-Db@H?#+tHRRp_Yan`roSh%Z{@d8;47MAQc$1{Zsbsm;h
zmgC)u&;o&(!&0?w$Io*iQG+ignuN12CI>2<0zaSYzGafY}=bq;-9&;RB2Gj)>~dtdTcJD6}G1U8PHYdVMl927d$NOq_;}x=|
zt<|h6G)op5YQ1#@7{HuSj&|g@%RChLa_o8idnZP)ONBbFh#Xrhv3=L^U@qN;FOV-b
zbQZxb72r-)iIjk|N}Dy}O%3Mu*n(M)H@VqDEm9C!bGC4EmVQZ7nNpCGibC7WJ;XfH
zsOixgWXbEI;=TqUvGJ+)RI>1?HrJTFhr0Z6U&_kC{!=06j}x6`BL$$ZY!B8BXDpP`
zFpEr3fGl;_Y8ot{6NBU@A=#$JB45mZ3gb!k3cz?e2HViGMNXYR-&ONo=CBRFJNJ=3
z7{SOOD3~E*Z1G0OrB0^QVQ=m;Mb@W_q`9Kq+cO~A6X^Csx`lZz1^U5pe|Lo1`B25{
zS*Qbz4eaClDUvu0M;5d*6^&h|B4Sh=yYOHSweUADToW9JtlPQ}ZDIyiKD^pn$Cmi9
z1CUbL5N7d;YqM3U_M^w~GzTg=dOK@<
z)vdPb{H}U)EQB6Nzo+jsNA5^7lmsN;Q|&|@j2&sL!Kf6L^1#uxLpH=L
zWrBFdX*LdQTJ4~_nxySVJRzpW-)qh4
zFl4QiOsej=TkrXpP*CLQdM9gRq4$U>A<1LPo0?aPvDg*z#zUDa+GIQ#u
zpiEc+cPo*RF?DGS)TTqCh(-&MWx|nCr4cO@W2=3xagDd}pC2mbHI>N5wg9>;e0I
z4~eIz^_XhY|FsEQi4wt!5a6#MmE>t!kEpZ5M)Qoa+5PFw((ht)Pf0|*OYX9X@1QT}
z%BNj4n6}+fyA3tpmU(!z(;6_j-^{}iGRaOT^1Oc&Iva!mCD5=)xZCA0e$QDAnf
z_G)rl@TRMa`bvhqh-u3uZGjgbM+^tjHX43Fudlyh^0z$vd9l)=7>z
zU?+CI@M?g#zs-`(rV26yx=4pgpfdu0HQu#fi10ZXIi)aHK-LJ`ysJ~>RDNGdJ3oIy
zBii|I!wgpf#Winj5}d;k<8poq`iY`=*jJ#hajDk%di`PP{Y?t-{4nU*8__co`R%{W
z*8Ha?fQXuP)*$eO9mxCQ0&yf=i-40Pc?*H#0sp}O*`6M$!~F)wKv8l$;jlAi`VkS0
zv*u`mYJ5m?t+JT#oOr>0%(F8Y8xuTj{&W__vY~;=0!Hk^;mXs6VoV=O9T94Uc1;rMAI^>83RR$2!hwy(K7EjQ+`8f3IO%x-
zz(KWB_@AG1nRVJe;&7ZKu8uk*>u6t9xsGCV9P+%s+1$r%Up1T;Fet@ilMq_kZlHCh
zT6UBI<=6;mS+>2bf6RHnk9SOY9B9Ez2d!5TSpPDdIs562KH!>-=1^L8wK;bw$}P4Y
z;z{pl}C}T<5?)iSgWj1=PmW#j~fmDlF(Ig?Ng!Wiph>
zTrGvV{UR3Mqrk@Ca!s5~O-zy$p<*;Hu;SnIaRr3#u&art>PCeSm9F#3v;VNvQDh74NTt_c5YDEB{`4BOezBk4#4Tn|_Z)rrSR
z&mH^UY#&5ZW-{4Wmj5G>Ct^j?Bf!t{xRT(`l(Q_^SJqw~Hglh7+;pB8UX}wsUS1Hp
z=n_d_j7fZnC`ctq$jwyH3Q1uM#Sv=JE~Ju;&4=y$c;V45SRKo8AS-DiEv%C{oSQ6|
zhO7c}e$uuWt)`AgM**hJ@t))*wBpPu4sSMkGcI=~w=dKob4+MUI(zWT4aylXmlJ$BZ0aKE;=REy@i{R6)97)RU4AD=uffZrFkG1XqU(B<$
z@+?8+h{00cx)~V<^OQDgxINV;zK2_n4ZX-DCiFJTG36kX8;duo-s@~S3{$!J-f}V2
zy2>i@M)Xg-8^Fv_eZLksltL~uuiosUWsPx{598~!ry?>BYlBW5Ze2@6>g$Sw9FrIw
za}5K}LSP(YxMlwbrx!bh*;^Z-cKl3!h5RrnfOy_~qfQPF*~hTCJMIeojifWLB+`9G
z3|(#hw=|WQ#JFXg_35?R{j8!V`nj93xgz;y7IC}ff9+WI1
zUDP@sw?H#jh$DFaosjDg1%pAh$GnUIOkt40Bs+0%I#8UX3~_K~;7RbCKE{3$&4@t&
zi)LZlZmz^?Qt*Wh_W@1~j3Za(Q{)z`mL+vNiK|o){}<6m@C*#>xL5#GZ7s|+yp-_*
zHoSF#0ayF@Bu`j3r)j^RYT5TF@ab_&AY=1?ZdR?InZ*X+ARty>LK?3BvR)@uZG)mF
z=}CZ-0IT-1k|_M&(uOd>gf$spr4nTfzQ++!`j^RJl2Q_({IT2ztKm}&<%5k=&W|Tk
z*+YK9p<+Om5~{9mq!b9vl~|(CpgJ`yEPQo*Jia)dK4c{P0AmVirb9ARWiY03vs3cP
z6cXy^qNw2tl%bhPR<--tkD;R$)6WjMsJ14k1Tc_8s=#^u;xZbvB5=m!6TpHh;|qt3
z!e*O&bTxO8M;|t>;?`!4u&;O-oNX?(UKl%}>xH#icD`
z3M1bP!6VkN3)}v8yclrWC&Yy%N`mP#xpi)+TeD^$rmu(4#3+gL^atA|#>@7g`aFaO
z83_9^jeHrbmQEthKcG8X%2#i7yWsfTz-}E!Wth!rw0)cyY$UAK5F+g!)AsM@bfp3F
zj|7NQ23Y+*6@-$tA(6m3)H&{6Vwoq8hU%KG-c(VQpA}ty+k)h&_L`|>2PYvCJZ^ru
zUd(X9Rq#}f=9xDsQZd~fia%T^!E+PGv;%T`iIyhPm5Z{X5n9v1E7cWsi|X2QYP{zD
z3|Xi*cK_t=bMMM?kl%45x3CbwvGXB#Cv9EQx1W}7cEXsaEpL`AYe(TmaBX_06uavX
zm_?jl-KF=L92ZRV;4aLY!fw%wlo?tVCA#?$9}O*BynjNf1%^x<&tS;FxI}j5YXDe@
z&3LTnJnbC_yQ{L9aqa}-FG$7HGt6iDJJrV$)w`{8Vciv2#M>)SDn+vkcd`-oXC4jM
znDz^gbmv^?AIjIz-8{&|66V>*O!m!_+GZ`+)@PY&2r8wFnm$CQ}!;7
zoQQwRS4$R037YZOd!It;+l%^RegGx2hyZzUSicF`9=|bH+^T?b>)6s%)TocjUB}~;
z`(}U_H!sn_@G(S&MfS>J+}(=va5u>?ij?CD&iU)jsbsqxQRmD`28@1;w%{vNmqj|L
z8w*$1cHy;PF6hkV)P0~+!*XKup`90H?71L`-{y+Ho-!GA##`{6$7KhiBhcwr6FKJY
z_~m5r0zct-*qki-A(W<|q~i__O|Z{tcg3H)mnF@IER=K4F6QE=_a^t*3{drSV)p}0
z{-3L^h_MtB`=H_tlJXP@LzJhGHy}Ov#eJNAuy2B>I}wO&cb+Obs{ZGh#6P*vcKJGw
zBj3Kj4oR`cpm_f|iBSK~Q2VU0wt(@`M}Y!ni~#X%kRy3%H|H8x~Uppf>NeCsjx1^HHFELdZm?%}TgdB^6i!2~~ptzWXyR9013iP$z;fC~lN@Vh=#MvBh7UfERW$2&;d+7)#
z9D2&}2l%;d`{(MZReoG9!ME(=OoQh~?sBFFI^TaVMwFq5d_dmD+f8gqFFnP^j8%
zIn6pIs>M1^O%L!VjIZ8?G~;MDhVP4RH1G{_0PB6Eq)GOL%oV)D_Gi?7=;h0z6AmuC
z-}uNCu79u(Aw(fW{2Hu07@(-_)tFt*(UBK!MUG~w-(g5?$hRK7XB$mJIV%ZQDv<@c
z9X9@c6LY2YZ>mGAt&n`szzs{qEu?E`tu$Zq!fsVsSSiW_Vx9C@DcJ^5Cbvy8
zoW~6;zptHOA5$a_oA~>!xcc2l<1o)8lFu;)1VuYLj?c2bgg2PGHJ|pJbSzB^pV{a&
z-hnv^(|xqSbf2z#sz_6~02X=yF
z2HRc1+uG=R8<)X&*Gl6z@m9IhH{CFQbCm7!Zqnt%?G%B}N?Ms}&^gAK|59J`g>&Ro
zHoWG*yC*>PbxBEr%r<{+yJ&ewMnZzq*DhG)P^dR^Rc!M<6Qit(!p`;33d0_R@C^;R
z62PF&Uq;G{9(eOD*@V>WkGg6L1qem3c=Z+kU?R(Kp&%}s?nd^}zBK)N5ApXD@QRsP
z8@mCwK|ww=eN*k9ymG+lRJG5s`s?dZ^q`p4K@ZBo-CRYUqgxQ+{ZinNCvW`oYeG^8ly4v
zU6`S{B14Z*&~A<;aOCD9TW4JL&{&do1o9hh|InM${V^<6JW*F~0qa>UeP{@&-I9de
znM_X3{xY_6b+&D);7m7;4^(Hkc0Bwn>#+3dmTvly8)cn}koD^%7PeD1(Z9y<@MwJ|
zSXVa9EIFf^CR8WUE`P)WLs+!{;N2v4rquWUAAAn0s~qy`-sKu
zQfn=}gNVPv?=4Z0SqD=ZdN0y$!j>)DV(4Qswo18q*sa*HAoGSDGPhKo757CI}XZAU*Mv&GeIq
z^lm=Yg4<42-YJrk%91<9?)kdak~^NRk+Q$~XE<%XhmX@++}~$L{DICt2%pqYvlGi!UZbIY$x;U9dGtri49l8y#AOp;AI3_4J+u5F8_
zhVl_%dQ)Vr{0d2~`NSDF>*g4zyV(Npc{`{NlG%4^IMms&
zxqH-y5az&)R{ICP%XQ&Ea}21}H2CAwFNVqZZ<&OvCSG5fL}gjz
zFPHSUEPjHw!6M;^s}k#btr12z;z*u#g=Kk_stL*7adMfsX~si89Zn^V(|kD(i{YOD
z$)-%!mU?B5-#)zpKiz}A?#I*FvxmHN|8^OoSa$l^6!atc3$kb}bQn1`_27*T?pYSh
z1&t)c)@;Tk@@;7)Mn>SIVR&-GY{+$%%-;A>TgGQs;QF1F$3Y>nR>P?TyZ7$*WR{Kh
z;C94kc&F7k_rnfyZYr$`^a#ehs8Yv(+X?r^+*7}*fT
z;uQIr%93S-0gKr9v=V1YqevF?LMicpGw)^|xhkAS793cRM-I@|%({8Q#Cu0{E6QGm
zg+~E;UF5td4{M$FefoFxSv~zvyPVsEzpdu7X&wMCu5h@$Jx!#ce}8f)gJbPOO{fT0
zd2UocDkkzSDu%>$ai|wUadKbn9LdL=YTHh3Tj>_N&-ClARGcv-o$0yIfg@V8T_IG?cBm@H~`0!J8Ws?<^>7oLQQ1GSBuK8|eHgJMG{%>|3v?c$Ghj-jNN
z`#vu@nK=Ff3L{Y{Q3b5ExeGkY9Ky4J>a~ymnRCQxG%SD|%T9qFy+vBb^5hOt*|cTk
zlFhq@cirWOxJ8KeB!T9E7L&LoLB?gJ!^jC+si|qHQwt+bF0p-%FcYcWUngrhCMVrD
zL@E7>bI#F|7HlrUPPJl(sAQcVn7r^U6nOt`q#Bk6^XP9GY}GD}XszX(50y}hJp7f<
zg*JhTc>uBq0^MHM)NXyhBts@+F!i_cpOkA-W5|c*ewvv1Pbzsg2an=~#O^`sK_eTA4)7+@Mj0AOjE?RT6zm?}BgaV|
z!!x50EI+Sm_^2@dY;fvdxJbC5Nq`LvuE4CQuW-r>tC(L{S+R6p4Xya(er$KWrAVQ3
z^toJjzH~jzeE({L&fxo)d?keN#@Nw9W;0HKmN#hj#Q+HG3`{wM5~(!zK{*p|4NBa5
zr>@i5A-yYS1^{!O(15kqT*IK^4XHpqj<#D(DeV{6S}GeEz#I)WIpIQJHn@V?CHd+iSQt~ZHZSjXmt9#RU-Wyv`5fu>;yyPYA5d&T
z_6bldP4*ITzP1znoAd+6o(No3e2fJ(ej}cctM~Q$=@MLoZi8a
z+!2GVcuRr&fgIS}$O~Wf>vpXx8ZTueO}8rT(*?N0RNwyk$=H!FkNoeb=6Ir~k$I28
z#>Q+ekKl`xV47+BC1hh?)GkJPicAMA
zZ2*|>cGj&hCLWc){?>~rCiHtBg+9W(dW=gNQ&0DPRquWpoWwVqW>)1H8&BgBW
zqr)W|^ac3u4%UkZiXX@V!M}d`u_AQ({UO{r7?pM6S9l7=Qhh6hp4`rR+h(@u7#QDO
z^T}O?Gr53glR~+Y$gf|)iZ`&QE4=!xj7iAREf8Dq+AA@!?KBlq*
zw?a=pu$9v3W89-u`@ys{%ixZ-T~v|P*q>YLQREz6!LPFk#HlRcj=WT3GIkgNXzq9MeR6XXT<2xp*o)ha&ziGQ2Zywa+m#tySWa~48t
z)V>WeRtwUcDsAyn?iJ3JT0ZaY`1eBqo19!-fzMdCU>tW98oDK9$c-e9FysW39+UL+
z40~>gWFKnBfDhZ~9n5caQnw6c!flU2TXbn49Z!U@)GxH$zVQ1Gh
ziC%UF!zN|uV`7qMVxm|k;a*ofYzQawSJEoN!jHct{A78NEz9J7o)vG=
z&^Y+se>y2p2$RS_N%eGB5Qu7s(sOH`X&wIvE&;9$T=0MYD%bxJ&a}?SgC_P(8oQXzSejX)OS9)5K`6^Zh$V{Blw
zLP7?P6Z>QRRwO3>Q6qxiTKA<0cbKt0`QamNBtj+=<54cu=T2C@59n~=p;5py8Uk>;L?
z9a7jW{9u2$k=_qWlzqbVfs3B$am8eXIQli)OqETB(Fw>)ji^B-7v7m=tffO7w=PyE
zM0g|`lckv{ItJI`19())fAqQZ&bYfvwdtx?g}G@xWmiWrKI)dUvB;#A%ECTFx46F*
zP&Ch&CQWac^yDWQkI|79kn}4TqGAK(Ku)ThK+sFTX=7o1
zx*6NT*aQ29zkrm)pg5Yc40G`HiCxY5b^iGi(o|3dVKxE$YjlC{xIp*O}G(-0)1
zG&BECs{l5ld4$l$BHZulW`C)YE3)*%18V>NxJq*iFoA*|jV(j}nqiG18a^<6wX0Pc
zFX+y)p2e*{7(fRoEJg?Hrt)?WU2l2yBoNdRuI@$#O
zF?Mj+^jeeeB#O=I+N+&1@p51jearS1!=nU5M$H2U2x20ok5yqV-?_X-rujhq%-_mV
zdxP)D-O^Wk!~4j{WtP)nEh>GY$<(+83xMtjRKVE!5j_0^-mW9G3SMzrh^wr}0o@)f
zU`WG14*&_n*j5dYX;RAxE(eQ|Gf)6MC?=68E*-*fb<|6ynx4_B4$JESw-XO28vcI8
z>XLZ!G}p3>24~^q0>JzYR8@)0tmKMDM^Utz#w?7xG@16G
zB-cMlcslvjs?c_|E@z+^5LD^&P}3p7M9G=~8zTf)JD?DwQ|&J>ilOmnL(4)BQ&S3L
zEX~zXrOH*tklFevrpi2_tVY+1h4BXmIg#}OPEChF9W6G#u`?&MRFaGb=T!UCIruSo^(OD8*JA
z^I0Bxo-2k?VH8BOqUqzL<`_(?HZ9dnVW6=P%&XvFktob&6GHjZENyw?I)E{3!V>}y#Cjkj4>>TCKW;mT^2DdMiTSGwrz{et`N6m`%Y0W~ANXAPK(lOgLoD>mzKn~zZ
zt2Yg2-LQkE6dYvsErFH9d79cZmsrQh*Z725Nyk~kNmb8}wMJ+6Js@Mqm+Q$9G@ZYN
zd*7hh~Fhk^o(SQ8_S%gc1t7uCGElG1cJ#?pXUS~U7%{YZ=o-I`a#L#@0
z^p7Gjpg)t5yf*EdP&hkpE+n_Jb+Z+YNkq_L+P*(!w%a$c+c!VtUoF~EBw%;L?a0}x
z*myio46yfyMKfCrXO;V@3?PVTWkj~5*amNeSYtaNVhOlb!b56xQQ>Ia>}LnuP}^CCW9k}Z{
zFDfhxme`-d4{|0@HsA1|WVnM=gKa;L4bLBoh)8Sj>{sybHo80N68|3ui+e5X9c>vX8g(qP=KpAUgJogsQ}jy}z6Su(?n@6dRl~FNYB{
zxzEE$uGL`pxrj0wOniWu=3~msVd9(SKP%p^(jEU&sFTz<(UN7=pp1ZWa!ORSzLZ=u
zT?AwwvRA8}gihIo8yOl5JkV3scRp{z9!zz8YxvMT@^txmUZIx9D+=?uZS(3UYQPt2*>cIT2jBG2&4&|dP|
z=p`XQsKO?xMSDtTbLRq4X@2+0n}}Uy5ILzrdIj+|;~cuzLQx
z#KyC8H6CK(?u3Eh?@!yQCnLQI4Y0FzCzZGKXFk(|K0m8404h*kKOGk|v=G*@piSV_
z??qaeh0A^`!xV*8f9Cw{>$8_8w7FUlk`>{HXtrna*uiK3x|(k$1t4o@EvzB
zd}k-ran4s@${QuO;A!KdgcnTmGdY_D5290Y-(T`GGC0qJw$%vNPjj5MZrAtL|CMo~JcZ#4;>9HBOQ*Y>7C_36(k5V43R_
z(Mn3=gp-ADpNP0Nr!?mFH!w&HME|f@1k-bn>ZrdA&=R-c0j(hKI)c_(*gj%&T5k4i
zi!pG2r`Adfq=k$5vkhNN2faE<i=e+(WU+>Vsxi0%}r%gI5w(P3==OB5&-~Srty;IByy-I1MytMG4D8-G=Gd
z~m;EeL|Y4ppJR!XLW+_gbH{ebsG@OgM>8})R=u|!Rp0{FoMM!M2IlK9ApLx
zuOqA;5^hCs4E;_855UcVkIYL;{)a>saI4_x5IBH7L
zJNq!Q+BEDwp#tns$_qFFrX4Mt_Q+1MyBl`N`pbtUVDIWr*qDgt!90Jf*#Pr8J`gb
z;9s~RxG0M1rlpxQAJ}QXN?RFQfmG8qXu!qtoT>kkiu1@I)fghqFcg^t5)evsiNUys
zG{)H!E;}38B@Lt9D^x-xY$;nc`u_Rco-BF>r#FYb^oE`020C-x`opboBre-f>I%`H}-qU{Q1Js|mJD@I-6maPJ;QQm=Z
zJ>!SAOsS891T!}IRm8&&?<`e^gp(y1?n=q`xFC{|QhR!ov<
zm)u7QDlQt!vcCUio_~r*-A7T&#E3cLE)Pe&idVx0^U2*v+6Bv**^BNJZRr|)15eK?-Kz!O%t-GT)
zp-*`chGGtx67ebOLn2e;JrP6&uL{slj3l(dZ_0*K#Ww5`Mz2d8gh3ECNe^moSF!j!M}}OKsqm&^2nQT&dfwbDy~vWdv^>KPGndYLf}ylegqo~BUaF@
zgT^a5Q365u6-;VYzz2ApG7rElfL@`6dD9-GT|BwwK)N=^xLjN*Bk_hbwcC6IJoUw&i;tc4?bbW{Uw1Y5Y7F9OIORX
z&)TS9P>9|)G$E^Tcb^nvHu%sugJlR{U=3~sV(bh<_(4M!3ZSUKE)OccRT1iozQZ#&
zZKH@!GI!vH=mAWi^|z=9yUcmWx7}TtEjr_Q`DcPgZt;E|0E<`K(VQSLP~P997|?Mp
zB#{0LD~(cf!a3Z7OAli;MxPF|$OaXr%ZG6h*bIZ+RnUVfxl`eaj^5>C2umwF|3KB~
z7j(jIb8c%|>yaC~baw%-&ykm`Q{5!GXP6D6dN~nx)dg&lwlD>*Wm9rH7OND8s8SHh
zt0eiDcWX;0RR^E7;zUs=sQg&B!(}Yck&Br%c@!Tv&j#Iy@X-L-{)4o+EcR!Xhh?ZE
zzK@RKct>=`_spA+|3RvbdG>ajKfCfjh-q)R46>~JTF>9+6Z_2E)F?4gk%OdiwPe`+-lB
z7hO$pDCt+Clm6k@*5Mfc;aG(chk-oC2JG)vM2xvsl)q+e4mvczrNacPfjEmOl|cx4
z)ZzdfdPU6*z8v`e+ebJRO2h|wcbrptL`F9xL4}zT)qsg)Z%1gZI+%JV>*Hhuj9oM#
zlCvhMYG&znDi48V63TdPEgRB<`q5T87FE`y*GnmuA=Cuw?9N~s>U3F{WBI(@#xZFK
zR4ERB6_0{;OFtG?3UYXL!-M1uZf@(`Ux5I*#3rhh@diFaD&rw9Yl_W53jtlfMC*OQ*);=rX`0x;XPNp>zvkahHOcG$V7&|?|3=>FR(LNy7@Gz
zd049QSk_T`w)p5R_+#Q8r0(0#4dNNRxoz(jXHd5lW*+9T?X8i%jFz=dTA5z{=r;fs
zEx&n?ME-b_qM+JbK8txjd~u+#>YyNTJoa1f+cy5$iFDQ(pX15&WaUuHR+g
z#wd(o!R|I3?42cUw3r?qMu?IaHg@Uf#1KNJE4jzM!rFx}yzkUDFx;2{7^2DIWf$&_
z>63u@9|6-p0=9ny9RFN5`#fuPp<3YF82f<{e*PCUG%o&1rulo$0aPk2!vz!#01n1R
zE=Fy_CN6I?Tibyj#=x^wEG>_YE#eD)2SfQ030Kv3Yv>0v`gphB%Q&zLa8`Z)voj2H
z1&vuxnSl{0yPOks+#cXhvo&VJ+%Qc94jncZ=M{DxHL;{w(MiyGC?xNyi)r_3Z%@$b
zS1lz~YLx^kGW7Is#i1r@M;bgEO{v@i^ezjR7USfQB@3-FXASl=M%Oe(H@8^}L>i3&
zjV5$`I>miNKb1V{`(8D8z(jtCsEF?J_qt;Xw05gP6btl8<6PsSkosU-EOn-s3AhGJ
zo@uvB1^eGu?{v30uU#2X{BzU=zutvG^&xo
z05BiMQp{7cYgUn+Ir?_d&>i8ZPDwJqS(2~ez```DNBb>O;Wf4YLD;r2|
z_-+(=KNY-7aa+&+v?M$gK$F_|o}CqH1t0Sx0ob-3K0yBOb>|;gM3CHDR&$!N3#c`~
zlNZk1Dc#zl80<4N5*PCmn3K*eWcY{kQ9q&i$Mt03k+N;=*yhM{&P_J=GxOiqiwjO5
zPbWn`K=sFEh$ZoSB@Fn&B~LC>Z+_iNtoI@
zV-<0t`TC-?y2s5H9hv$zz=HM;OH@e!ZR3cPD)v}n#4D&K3Hp#j_l`g(mueF+pt~
zb^BA044xn4?CK^^S7?K@*|(G|jSvHXJ8B|T$!O3XxDZMCD-MJh^mWu}b43=w6lz)}
zulkhx-#4}P)3FY9%W>Id5OZrMlJeMGD?Z
z2NjQsseh&l!`5qu4tyi>8j6)mVCYxevA_&rz
zwg~IS@(i9&c#5$l(0@ZLEmJ4@O2Nw7{UWmcpSnG+~jq*N>PFmRgzVd>}mD@p<5Nc$(8t!_M{hq^r;`f~G`}O(!EC?)@
zw;Cz?A{2r6J;(
zXSuNf#91(gjv#a{J{%>538R*3Fey}#jE*&1wF_VMg*x=8-I
zT?C$?gk^1nW&qqg#PMN2y7jpIuJMB5lwigwo)U{kz0l0L=JFH{ma;b~%EED&GpgAE
z8_;O2n`@fo@X@!a>OO&ljM{Cwd8k3%t+lO3If3@KLw4$Ss_WX&Yt!O>C(Fcaa`!KF
z7F!#Jn#pf^k+w|LNpI67wuK(EUi>DDeDR^Q^;YE$7a19H)_oyla+tZ7DqN71+mC#H
zd(6^dhoRcX5Ik3qso9EE98S$vQ>ZQ*JHT@;?%?hgr@Fx6J|2}vx^3olyJ%ryAslGp
z>Db3gf+>i$Dn;nLuDk6nMatr&jka+MMkWgXj@IC`MpZ(sO&Y%ZFV@g`|CAT|J6mi~
zFU?_iy`RqF5zk2Z1&YcKvseQeiLv|9$l;hV^|Zo269-JoyLH+t&QcZV>rKoD#p_#LbeRT|?qQW3|o+oJ7D$#`SBlB-z)!uNJS-70`x*MS@_`zvzitOFxoca!z
zc@ptrqMbR9#Bv8Z`Q5TP;;1PfBgR_RD#J_Ni4kL992}BKd9b1l<4?
z_|6x1BE;sIa4iZ>0mW>DQY7s%WT{p19Y$z>p;7evo%rYZg6Jjg$8j@3Gy!MUSVa~5
zfxyh>My(P$xYfx4h0-P7e2d{{byldP(y3J1`;9C*ye7U@fFn^8vXJgO+f6cRLLett
zQXxgC7Jte;zSA3^t8Z2#ZB^xVT0&t}f_+tjDVAWI*+>G^-n8*~&6z&x@{+&Xp>GJf
zl>cev?j*sXKG>5p$IiwPE}(YyN`;XT=H*Yt+6ciIg`^!N0>-n~kGRpVT$WGZ=UY;WJJi%W*87*Egc|8`(_kye
zYYwe2|FE0ad;d<+3n1~Ml|+8kpeAiSoL|bRV%M_ps40~;x_1z0l1tDrCEW?
ziSA3nv+(8WC6FrHrk!`&H`sQcYqKOdf+%fT&*N?1X@Qf=hjhT_`vW6T+HE0WmDB?{
zsmb>Hb5AV*m`4lB2nm)11C%R77a#x^-HP9fat*dSpdav(i+JNp$w|mf^IUtG65}gf&(TjZOPX$&BLmtS!d4ggCbTRu<@NflTC~$Zi2BjKGp7%ZFR3T@e
zyq2Bs$TXmmPAw#3gTrc4ZkOq|k(M1vd5n5?b|~j2P{)^++m)(d#sU)B3J7dYug*xV
z)Q+y#F$={~loQ8Pd6>v}{jFxgof_pbcDP8Q4H{np&KN$!h1g
zrC)miPLnU{VyN73gKS5_V^p*XX$giV<6eO((?lP676(rUZ8!3ao99Z38Yhdox`xR#
zcfjeuM?(YCTy)R(WY)Bb24Lnx^mA!tz}7p*8fI;UePULf)zAOj!$NeAE@Da!i4J}5#DWuYm
zN>kFSy+T-Oo&VCkLo77eD?}V#s
zB&T8Y?CNr}M1aj8*#Vmu2RFTfCBh}GSfS|jk=JajFx*zY^cTus3FmAN*t?p9A@NK5
z%nT3RJL<}FmNg!9yP^?eJyQ)Y;vA9{^5@*vy2ruPAvk%B61Na4?j}I8svWq1x2}A5
zYFRg0q)}jZMaZM|)2t>}1ThrUT=kEqzg+PvH17kCC4jh=oq?x@kZY1wp$qYKeG0sw
z+-@aCzK+{Z8`-#Z!oL_g;lxSH8G82OFIfNb9_&)#b^GCyy`$*?JF%kIoHG7-vK!kLV7x*(F_%uW?$-)
zLtiWYx&rJJ9UuaH2afZ9C?bwDIIla`Y>4olUI=_Z8d&#Ly&*9sznfMgZQw~EZr1~I
z&6bKLe__YbCD!~^q$M(VH`xT=^#uB+AGDlZ!g$kj35iG-zc2CQZS~dpji*&&`yx)%>eB)oI>g9K0plr0!qC!H}2(q_b=!1FBxR0A9!
zDKFY4lXd!j5&+2g18B%|a~T9wvIa>OM@-ma&C9LnK;=!=>~JQUitFImqK|;f`27^<
zjCnD>X&Ps0qYK|oqN&zly`(@N|7oqNj!On}Rwaf~FO<9#ucdpun3*l(RhQ&C+
z>>O~@P7OtT8)|JqpA_S6f|fO$&eIl=!(7T<7(rkE0haz}^bso5Dt`8Ry!I3#O$h{)
z07A{!M9J78&G;4+Bh4rQ81nm?_rHv9=fny!4=6Ar7%p6n1cFo7oqREd+Dt
zHG7X1u+Jz!FDAhwcr4;DCE+Yqk2UIkiKSS5!wU)(C6{~&=rCi*w+IyZBdu~1I(qrRuqZza?iD(x15f*peKPC_G
zcUMlLgPFC102XbC9cLYey(A&*F{YRg$VhudIiu+IEmuy
z9aMNF3P{l{s98Ay6G-`P6*tXZOSh&_`J0Kov#Osg!aB)@GSDnQ;elYReV<-uDtrz+PK3icXHmT%~sT>f#}U``@7%
zX)fkTcipYf*`Nq^+QdjIB4*~)`42Ls`lc0+v*(S
zJ)BTD+?8$+gH(jj^Hxrwl#23NYj5kfF?oZ0nbHV$-+@YOa|nQ5?v0Xm1G&@IEJ9mh
z2K;Op;AM#h(YpPRBtbEuo5~@u8ns>qY8EyWbu43T#^~4RQ(^Ktf(VfMW)X+-NFJ;|
zgCy49)}!G8tX?9&YW7g$Oy4ZKBR&ohW(viniRVn8NCLTlpc_aYb5Dpb-%t=jq}yKx
zQjQ&Gkmst?3yAv+!&Ct?L$AIc@z}AY0i9$O0D~l>d$@n-yf{?xxKtr0DSbTV&pdN-
zK5Vd|iKS8`ulRkeZhA%KjtcsAMGE3zg%M3eP&v(%c{$xT1q4RpR|n}HU0aJ!?Z4tL
ziF}B@S~nM7;Qy~B|EC5J4F|pCzB`<0i0=;P|0XKU9jv_=(-Lri;r^p4(EkV2o1?C;
zimHhfkP60Orx~Or_<~ekY>yHd4P(!q$YCc`0Lz6sjL~I;kcFye;hMU(#pI-3rTK}g
z%Q$*^ig+4-{>U#I2o^luig|MBJ@XL2f3nu_-Sm8-23l7>ngVHaZ!R)LNTaubIao6>
z{odoawu(5YjD>y?K3GFaj=0QP-1HWBd&sAeZb
zoOax_kw%Y{%JitGwI42qj_y^Qn>y<&ccYqyJhbdrYD0RNLX0BAD+fhVHD?W-Ily6Y
z1vG2@AS#X447OIwz4f>n&mw1^H+#JrZ%1f0y!ydrB;&#+28)?bywwT;qcbYE!mf38
zKbL7MY?nJL%S4Jntw`PU23&#@lzyWY_iLMP+U;=dll;nwP5Oh5w-+j=N|)nZPUPUD
zes10C0%qv2$l2OMGY6BDYRURc{ea)*fPJtB8$O!#s!~$MASu+wZn41!rJ|~;3L`O}
z(eNrDww*X?2D>IKSzy!ws8VR$Wx`$ZC~LUxx*Aw-idwm~@7^69>UFMaF|)!?a~2-~
z_p2}kD_q>ybW3lSKXcV>+R|HsKGcYVE}0e?L8S>;y2Fj4Id)5@8l!t4TRLct>YjNr
zbELs=;}eq+!Jszsj8jW-=j%7c$4FI6@VN;PA0lfsm9Dn4bLLe8F!`wn6jORY&G^%J
zC5O|WHEY*+5SW*s<}A%pZ_z4wrf=-hvY#{krCT_fP%fJt=07Gc&
z4aR}_k$^S8myXC2_t!THy4;a;u%gIlY^NeV#lD~*dg`@P*$~|(K?78p{(^drv
zt4u0$Jr)}++q1(fsXG!p`e7Sj^2jIIVGe=baI*LVqvhDm6(6^OLo7tzksRO$Y(#Iw&@@h8c
z>t{RElO5qi_`!nN10`#;6qBr%mt-z4>1NH*J;t~9P5~RcY^=AS7vO-)S~y9yqC(~n
zvMFgFTp?i5gfEI$vd{mT&ZxUcQvduOsI)@)AEat&4-`BgNAuMXcLe>5A*stmn*rG=
zCLRlyQlvUDeo>xQh7J}vc|2V!FeG^yzX+YK(qm~0{l}wJR+0SrrgRp^nLkBW9jd7v
z=UGmpwNJ~Jf}nqcj&w8`Y>8lPW(McYd-u&$)^k|Pm+v2Vpq2x{sf0UZXizT3{X&#}
zBVfGL-GNGgSW;s|OeheVz*tl|Dl=i=dN4R0hp1>=%>~|ol>`AHEXwJ~>pIIaZD_Fjld+?dGgoxfVLY$g})EWwN;mJ7}4&
zZAugw(zakS67aHDq5Da)Ng{)*
zY!ZtAHfv;#3T3W54X_j$gk>m*-u8p^7bzwU$QBLxpzg7f0|Rr$!J9lq=jHr#y_h)Z
z7`ySf*dUIIQ*u9Nw#0k*YgCZlldMTGwMTKHs*|uqTjWI>
zNIc`WW#1{%s}pjj8_Sq(2_-2>O_$DXeQ
zMDNH0M`4jL~?DOKvvYy=dP5M#HL7{ws)D7wvkm;sV<67iVJ1LJLrs
zd@e|4qtL09p0OWe_jujg^ChDaP5MyYh
zJ_wGDc~>5@QcH7yvTTMobd|#K^DsJtLU#|FYQH`PO~LhKSzIsC8GS|ULuL5FOLVxV
z^>C$CblCA$7r7_-&bO1qs0DSmKG~oLLYibBk!5>Om*kV`Kruq~wNy82JdwLy`tt4K
zsYK-oe}8SIqi)j60pe)kZuXBEAh!eH;~^})F}Hs18D|*Lt@QUzN5Ou5LFReh_*_q+
zJ&`~mtQeUGoje*&c~5_TyY;BhaY263ue5uJEjF$3-9{QQ8`Y^6xhLQ));3K1Qw}RL
zv$%g#xnq%qoggbNmfTwx9m)FC8Q!E(E7Vpwo((~t9x48)I;<(&$H~qQ5cZ}3t-V))
zEICZ;pw_?f(hz8$&w~r~t0#OrKX00qf53M9wxd*^peQ-6T{^d=L2kH%Y*&ka0igv#
zX!F6JQ;Br!i+j83j9i3rM|+_cEJF6<%$;Wf^;qvO2F(mc_%-R2rL!1dRQmZ1bJ;!u
zq&b`~ht5DjHyp4rOdzQYC|>0%^VO%n&+o_$y;hPGp25auuh6LO-&S&mtX@gl+II@Y
zgiOS%h2eIo&*<0iX|$^dU_}R4Zc)*oPj=8?mpyBl$zu2jvU@OdF1AFQIMWc@uEC~L
zCBCGmVKCRPBUQCb`e5sHjViDwOSK&=Il5M}px!a^L=+j*Vcdgk-=VkwN6{CjM`!??Eptq~_=jXHdUTEF%uKg}
zbgZ+jb!3`;mPP0uizcj9cq)3ei_S2w;07
ze@}@M41y!)qx3?1kpxbaaE5b=`u5`Izf$#<{osSJL2M1^L+stbJbi#N^#e&34jwUS
zANYRIGt96{eXh*09KbdgSLanhTMl5(b%({l%y87h49@)kAn&J_4k-6RCt>D$-?mNy
zkaLzElL+(y+MY#nwxfS)V!6NuG{;Dmom78BiuL4q%F<5zB&_QdDSYC&B$6;h)9m|A-T9GReQ&MVmPXqXsQ{z$jN@YvdJ4b}*x_k*7W)Osd?9@4jy!_*SbTl(
z9j)gSI1G*lAfaFXm{dlr+&gBst9fz)rq^;K@{RJ}jjb&bNT^u1Y>mz*!iiVlJvZPl+Iv&g+&>1~N*
z*sBR-CwS>V*R&@#Jr_UlI^FSGs)!$Hco@~ZUDG4BZgvB(Zk$yH!kLT-@?4ik`&;51
zM|N%%i9hf+jN6y#)=diofB$zMd(2thdzYpl3rw1pHvk2e_SFMLlm;9N$^-ZciNyU1
zyW7mrp;dyYlmC88i@)JL*>rX6`TTf+7Q%r=4o!?9inxQKV4^0|7NH47DjsB^H{BtkOsJyj83ut)}oNN+*bN|-)>^F-&G8^s+&o^has9aK+;%I
ztV~Q1s|zAReZ
z?b}DRLN
zyL0U&a&BAui5<4+xSBK5CAF#F{;1o8R{O?;uesewP5vjNtqI~f?mmS$7Jdn2yAB5(
zj#j}Y3r9hO5l7TUdNP2Ca0uV5V052hAVHHvS#QJ%Eu>Y1pJ&Iqz*?{k9`5Xci09zX
z3}?c{M`P=h`txxlRrxqQZK}eYG{Ecn)dd+B!en(LIxfe89$Vc%q>m6Yd0u}h4Zg|d
zD5l={(-}ARS0oyBd+EUUuAaXntw8Ot(ljJOhD0e+af+RgzLJ1?!m7sR1jt)>Ol$d8
z0V~n85M&Wf2JR;$pIO*nr1}zsLr=+gRT~ha!-GzXFS&E7Ue6SQz0crP`_52bwo*Zy
zP%nsavjERi-^~Obf5z&4oV9Q~K|uHyK_MrO=shag1N(Q2iWJmB_JTtMU=xD4Na({k
zgdgEu?v`>QZGz6Wlp^gMh&;4RQ&s@R1NKaFPyi-^|EKR9Y=;)S{`Ow#({5=&2>(~N
z*l7tapzr{+PY1$Ad`NGYdnIJpR17O`m}ZoGnG`f~>hBPP8IRt$QO3WXj=wz@c-XBx
zXJfs#+nV%NXGcEI;$@f=VY>xh%jxfQ1NZahMvb6g00>j;w=YUY2F6Td40j+R6PA#K
zG#si$A({?joS9Eu_>a_UQ6{dad}Zp3PKN+y+Z^m&=^kvl@6t>4QtnFo+M+uL#Zyz6
zV=8Ua$>!nwkyU1yQ;K_
zCz;&1=tMd!aLi5STZf1Qm)#vKWTVU@SK6{|E-5^l;i_#@vhp{ImFtseCuUY&ySo5Z
zF62Hia&9bByBms;cnWAVbf|FtmS}W(6xcqvnA5X=Jl!FWcF?EUA*Kg$Ng0rei?qER
zHW;RrCL5j}M`6R1min1a@q1^pThRY3m8(=2Z)hJr-C+kblNiv_aN#8UZT}^cTwk2#MzrA}_9^ZBt^>
zJ8qT%%AU6BYI;V}1<4)>&^KNEpBagN3WMgJ0SRL9yD}~y((Y(M2>zoq0E{62c#`^x
zsKRLc3y977(S9%_rBLEBu#J8ZMz|zu(oEuVGT)}8epr3$WzrUXP|rT$?GH$Q;e(L7
zG03mPNapP|2BrL_P!3+#=WW-S99CD}zpp3X(TaxAvIvqgl9-ezXE`Zb6=5B5Fl=r)
z>U0gJf!U<*aD~3vC?!nCM_>s6-XV2Cd}VpcW%cqNheKGmDZPIGk)=eFJ)
zJ2-2tPCiU&dmRPN9()Upk=B>o*zq<=ICnbux3g*TM!Vm04zZ`CC)y;7oA=}V`*`zH
zSttWu*lM{o46mcpNMg+c_|&@Wje~CgqP24B*?Q_;kzr-$8dCUm61^9o6G7gOVgiY4
za+F<9g^E-a?(df}4e>%_KTj04&*x9~MgWa{IkPE)cDPOAsM;1a%t{qX3|VIRR9u(2
z(g)Ol(gRr7a=}ECr>)BJngGy*Xn&83rU1??Zlq^bPXn8P-p{2Bo!dPX$tmju&rZM-Tu$t}2
zdX(@`A=WWd(XKPxgI2^Ibc9vy8jOioU_KUvQyRy)&y~EsmZ9Llr8^dOYK=c;Wtzv2
zV;{|+advqw1wRH+!LB{pMwmbK*L1q*uF=Hl3E`X8w@FMIaM2xrlf1dXB^*TT_LG8y
zUrhWo4uKA6-?ro&W(1k)0qUU+F1HfpnyG!*fAOi`_p?alG9;&Mgn0(ALQH0
zjnl$SUbB&DlfP)D_hNs2YOGUFw-+(N0`k-qD51K;QQiWTZeK)RcMM*0ZN{}<4K@e-
zqY!;sjU;cW3pvjL_&uY+hGf}1!l$IzL9Q~xHdF(aDSI^L?Io`yagBJ#
zXp^*BMphGN#n;s=|FYvJRUtTO%L=}8Z{!!=PYNoT2MHI8NZu2C7|pbocKBXf^>BSt
zmx~OdRE|HvMJIrB``7%@RsVjI1{St4GZYJN}lVTPyhB*kK0W1Eo8w%g8@x
ze+(dPvB?{sz+ZFSySL?OhnI!$%ck?tkF)4+uw*Y*#Cr1X59&97$Ft`}n%BbxB{%8~
zu>W9T8DaV${Efn*NNbmup8sX2T_TA&f1JsBi~?V(5h=HnQ{c3P(r9
z0vpq$V022=uJ>L$6#wD=q#o+)zMz23;i&RAQ*3Mxwmq*PDf%v~m*UkuQgjMM+M}pc
zQ|?;Be!f;8ae{X`)#(-X`d-f#eoCRhO5I-G?$jl^{T#)DJooMWcNuo7D85+JQ;1T(m-GMy=TlqFHYoCa;gKJ#z^0ILsly>z3A)7{wgFI>h36HDdJ8^bCCKGf8o
zYLK6{nNHcODwzR32b@;u=jL15E#(#_$Jd|J!+(0Z(YM6b^^@ZDGf8lFTm9Xg;6
zDdpm$c=LRJRHBGHg0G{Fon_P*8IB?pgbZ_t1X8!kdK82SQ~L17c|7jr#w0Jr1AxK!
zY>`A$e1Bb@n%kwD$mLcT-q25>@F#qP^)kARp5gVyD~bFVUNOZc#%bzg=JE!8kpc+U^*~2kk!I_JB|F9Qv6HuC@3Z-0H`M@uABGm`c!trHBBhl&Ds(v%$57(
zbNVYe`Te1R@cWt+$GE{1h(@`PUBsQSXQnZzJ_-Fo6!A{Nl8$)?R1XCV3xW|c3Q;#G
zP6&ufXgxJXf*Cmyqcas3qa=X#!V@zPj{{7F&15
zVAIS|)@L7^Ej}gxjv6%&*SbL1sW515L;|V`erNFL>lEASh9#%}^37g&+Dxe`8$*>Z
z$;;3&kzA7JtQ)j;iOOzV5no^^DYiWN!_A#F&TRHovJje|`FpU@Tv=UiM)yQcLRx;J
z;i7D4QiLXLjDaO|{+acDvOQ^HqTxe(?aU^s)eKW!SFp}=QqgbmT&6(Z`7r(n
z=}!@q9c`1J$34A!d&?whNao{lp_o95=iMK(%wpO!sXrZB0dX;okxhrS6eE5@Mm3(_
zA<*+TCmBzCh-L%aUg1Qpl%j;#K^M?3znO$IkQa)Zt#?A!KZb;&mieG&;S?Gi?}+}q
zZ{A>qKCaMdgq=z+l&mBs-Kz@C)7%=ZICEi=l60rH$Yq379gnz^D^oA(X1rzHOKl3R=_{?aO#(@Pvk|9TN-g3-`m60C5cu6|c
z50_(O+t?LZ^eD+dG-VynvU<(kgdG>EZ*9t9o82#Ck1HMyL(52LT33%BH#e1GcKsPV
z$=uT^a_)M)?5L>0G4(-#n1x5>_eb)t;{C&CgD%|88xOfqUb5JoWu%uwLYxSr+Xf4AXhKlpXJeQ
znl%vKR}-@AhG*Z3a=a4nh~JBo`2t50QG5fXV#Wu4@8AiKhKHax{=j%~1m7oKN1XKo
zqbBSYy1%tWcf%ub3k38c^E~W1f$Ims7zhpyfi~jh^AdKu(VTM&Eg<_mpg-d8$3imi
zNj{!{s=<=aJgD8%s|l0u$YfBV>jj`y?2ZFt-AMLEyW9KzVKl%oN@n
z;N&o$zX5UFQoL*=eSw{|dHcyMsd5SYH|7$vmvC<6`&y%MY@T!}W_2%8;c&c;i
zUX{@%pE7$h+6^C(s*+S0H8l?YkJzUl#3jvn*8EwjaVa)fA3B`H#g9cc=NWF2
z6!sRZ)Imy)B&>K_oau9b`L{kR5>9)umJad_tN7{aYb}7|&b8Oh^mg?Yepj8B9?@!t
zBED)NH9J3AY?d}ZzgPi#k$Jk!IvH^93`!|AB*|nMk
zJ9w&ADg^WoW3dOnWlNUFgl6m5WM^}>tsLnX9Q+J53fkILRr?7*uK>LT&^Tc`iqxuD6}8?D3&6WaxU4L+uYO9m3{pi3^OWRi6Tx3vR;L
zOdp!{3S5da&-UW=oCF>?(`1YCobs~fn%lv336@pboy`hW9X9Wh-r;L}|8-&3)Frj`QUNs_OIyig
zGpZ&OG7FoW^*o+TmVsy1nvR+d0Ciu
za+WeQZ3=VJcJshau3?3yWY-P3Lj~LzWjG3)_H#Bmr|L0Ngg*}olDb4juvW{;YvPt<
z73e_Pk{nt9Dv2MZ46d#FXy($KKKM&9XFNN9^Ytf%Za<`vUtn@+)|uD*t>cfU`L1D@Tdw;Fjh|Q
z63=+H^b6kjI)?Cuhg*V3%<40xtitMAn|_NMiDtkCHQ-J%9nl~(qs7!XICoa=rRAP<
zsh+K6arhDAA~aH}cxa{^WX#!#Tr97}HX%$PH&^5l>Y~{l=Ob!Tt&R^U%p&XaH0UDB
zerfapAReLUJVlnmB~^5|dtm~?EnU-orC9ugY<}=Q4$Ow7XACGwwEv3
z=6Jg+(+ymycBbFogU%QJHQPj1Ry_RpR}C!#ploKxm822Q9=ZJk2|eld|MB%s(RF~^
z_jZ#eZEV}NZQDj;+uX5j+qTizwrx92)AYaFqu)8-7~e(4*cZ86bH8h^XU?@K`(wK!
z%8d7<)e{iKoW}ae)|m|LFclZZti|NTXz~!zXEki=%ViN8>%{xWbZP`f_`rV(8b}fs
z?qV6EMj6WVfw=YwMo9}PiTIg{pw=V?$&W)nz`
zDGLO%h{MH1Cr9+C8gpKXgm8#*@*A)WWhu*da(YRjW;4CUaXL<()Qx17a-RZ4G|
z)d$ZQ3Oj5#EaGxCUkDv7<0P}DzS^I%69hw(7h*n4)(fs`_1UD%w_NTl;V>vgtaa+@ubWPnVbSURY@HxVog?JODOqp7;Ml0
z|6@#NumXlbd{Dl?krHJ$>KFDv+14oJ(P|gc>f9Tc&aPUFae?c(4-8wLHAJK|bVrt-
zG2UraHZv4GU*bY3RO%PUnkWpP^r#P)*5@AW$;#o+gJ;=;H&an+wIj2`&>e`_xEJDn
z7xo>JH0iZkge>`5Q1h$i8uxXHTNbebnAdx&Tc@ru7j6dECY^Cvnys~DUCbH=G=hGd
ze)16{{>0y^_X&12Y{H@@HHW&+Z@U~{V`g!)THo@jsb|VFWFgejS#sJtIuj)=)ChUrz&*E0yvN1bLTC`S&BtIQxrFjN+0VP>#QU=p15Oq)j}z3>a@9-=13L~6wV7btS>sLfx30Kh24gIB#J#Pup^e!f?b9o@
zrUMYi?<63;Fp^D%^lAr|2`Y{PcSH%HqK2`u`vydcg1tZcsmT~`e)ko?CI?l-Xs{qh
zsu?;^)~`y?><ze!+G;^rt3i)E{IL-Ux%2X3N
z8!l93t;F$8c0M;H_WDzIy^NDPXmlSq{Qf4C4yF!<4oh$eB#ZpFI|G&AKxwkNB+MUG
zv;jfjNkLGe`SBbqicn}RRxPdAO^2e$vT%xFjz2|DQ-j}MfO{aFHVp=I;Q>UtcGg?a
z)>{IvAYfz&ju+%OZ~k3;TT#}f?T@LQPcNRQC*Eu_PR{N3Ey%7Lm~>WVU@H&5CXbN|
zG2vWLH#8ajQG>JMtAlCEv178z#!p00r!vuCI?g;gPrA5u>)_lwP6YT+mr*WioeSIH
zko5Kq3S(~4TB6Hr3KOhV+5o>C1BKg}YQ3w!`a_D4A-EvBx1Jo+lYO%VBz$lpn>#SK
zr7v!459elvW83{!>Y8L*vCFLo9~=UJ1{>OQTe@3*N!|KYE&0T2B@*h>1;(28t=fir
zsjP}YrHFI1xEg=3C4lE@x8ks!YSCufw$JM;+}cNPcwXHiRe;wXq{2f-SjNgwVq1~h
z5Xw592si5|&kmLsl#-EVaeG2(X87LbJJ1MPbyrE2LM<9G1scIZjfi4HOd>-MJej!l
z0odiO0Btq6Wp116_Ga8iWA=zJ+;ca@DBH;co2Dd-1IjKx5I|S}@zA(M^!g{%&;h(T
z8cvn?0`u*`Fo_?$Ipd^fXVu=!OG%h2{B}n#9#p9$`JqfEuRkA}z3Q(>N!x6p>LIIo
z@h7fnpV5keR^e}JzX<3W8^rS>Ym&F(enbDqa`z_%r^(JabPF79^#VOUy#E?)rQTG0
zb_DNbycGb>}fFrK!Z`6e<
z>G71~GMM(>4)e~GeR0kSN&g=Dj(i>Y<3v4QD_VA>yjpZ^@N%RBUhKGDo0`$r?*&O4
zv4jvD6uvcL3Zj&OrX(c96#B$$n3l{yZjh5tTYX;9Jzj@6g*PhhD3thQ2p}@ctk9F;
z%;-J{GSn>MnsXnXjco(sKg$M`ng(G#LNBy*7#=N}~E-sEss9?lMDCix
zWEB>5JDi2qRNlI%8?&m|9JKqVD!ePGQ*~uF;m$i0L5Tf^7}6Rkbx6a+Mg0;7i~|w_
zD*YIJ<`@G&U+Ut1c|lFDCnW}&R)DdF)gGN=w*C=(+y1s7p{8P+i6~lv^Pzszwh5iF
ztacRJbHPKYmX#Pllb*r7ut2}#1*X{A1ZIliH)phXW`Rh8?IpqBjJ!MqyFeURqqe5KTAw+BM#`9b}WfFX8)iX@4sdKTKuG0e*cv<9-Ki_}A2Uvt573HD);eAuaDt)6dEn&=h*j>mNVph8;oRUtiXqRE!F8W%k?pIVJcJXbFiQm!
z7T>NLtQ;3qxnvQEVYlA|=@bvaP+j6`VrZRv?74)*u>>o?t
zbUC_^(rblR`q|l12cwl_;}K)iQ6Bx&y0O2i%^su~!MYnhWrhJdV$mK3phhw=PBA#;
zS0XizNm&(O68_!WAqO|pJjG@6Ij6Jp+X
z@b**IS3}#vPSZWL^(x4qu=q_~MJgeq#EGt=9mNj9Izc~`W0fX8NE}LRZC`JQ5K;T7
zF6+V;Dwh8QZ>EKyV9f#ra2Zh;=^|{ar0z2uC6h-7FgPo@Qo>ej=ItyJ94ZJQjiS<6
zzQv%%%JEARtI-V%L5#A*80HN*!gl3kH9Fw^rqP8+Inu#L@B%dey8UFl>HR45E(0HZi-*aMm9$w-C4cG|{2qjnU7~ZmW;rXq!~KGYnQS
zYK*yh$xFCV1fHaq=oVR#Gn?=gMCz1SsBb~~i2K+5ucf5O`_FB$Ur_+32LZZ$rNGgz
zm!+thrD*>ca}Zy=K4MwnWo03ZzCuW4Qua)kX_XkWJVtl~Ndi9tpYVoB#rd(ykXVI^
z2t$+xGU(BxC+PZ_IG-gB@(0dH(aoPq2Y?!f&Vm0RKh7QguUMIa+?Lw3d}?;nXLW!h
zVwV7Q5}J8?q)nItY5ZUEz2VB8)Mt`zDd3pF3Z*T(fM%uf}
zQ{CVdZuMWhah6eExhB-}b2_e*9vCdc@Z<$ncuO@g6=B;zUJsM3?FsCZ!{LRLU@P3h
zS1&Yn@PE>c$K&BnT;F|L2-~CsSoeKs&5-YsVs!f%BA9@56O4~o70C2LQnt9s+26G_
z3x&`&jZ>ITV_#G%MM@w_M|E4p7;@S)ZC&qqg$Lmo2en53;EjwA18MGi^>y{V>m?g*
zlU3{T57y*_!4>B|QPxx>Sby333#8Bt(u7-cMHQK;>U9#sPP`PiEZS>JdKUGG=D!tQ
zT~Q5qfF)!v@8mNQBU4E2WpNpBEQ>B%?@?9D|E4&EG)$zSc85YumE)f#W~UPvp%_&T
z#2X<;+W)R_RMLUBYWiUI;?Fgm+u3>M9n-kvJz4p=-~LuO+H{91>jX?+5YJg(gFT7;
z6iR3YbrsjCNI^56NJvdL#UTL5Hv+ixphNz_HxkRs&;AeJfIXmF8^ijNefq?)J{Ri6
zB&Wvz1>v?z5JvIZr(tPgm0>82N3(Yu=(F)8c!KrUKaE@948TW(^bw+PcP)MwuJs1c
z9yPpw!rMn2!uM+X=61^oM0RncXaQ6
zw?AcO7J>1p)2*K+0Cwsd#wfpeQ6$g<0viY!$ZUmI(4>Aaw^$(326JiTNkGxa3^f5G
zs1kLOh~A~S5=Y>?j*p*TbstZ)W6eBs6*RO1xWAt5@pZqn|Gt^3{qb}p-}}kkZ@>ye
zC?SzkPAO~BsexeMrU={{XAl`NQUhwg90GHK2&@WX6s#U=5I|1E#o3A$)Zg4dv|LYE
zfSn1N1D+podZgbf!ZT7z^mdo-HzR6&04>J?;sF94f;Ys=;zDb7UTNYbPv04G%^(q(
zQk<$>a?Fu+rK2xtrgSmxN=0n8jPZ7eYokw%H~0{PEYCUJaBcaJQAvtXLn$^kzbU0@
zw%R3PBR0L!3AoEHsMh|XyPl%mB1_(rZMdFaU4m9epZHrca*
zV#bbIQ&n%*4Jur2in_*N*kr(A%&|w3#YxkV_zC@l86YWQ)(y691~XxAh6%bi`bF4k
zoK68yI}uV`tK#b9$vM%CDb$d?G6`F4ZQny??V^vtGALeK3s^P7r06I+dgwTSiH(hA
zh6y50mH#c{6kwIZnD{iQ!uycMoS!ie(gSXGZ(40U$0;2VacV>?erLMy%82E^_A@*Hi&Os04(nYon^QmkKmV*uTYS9$>SGK`fMOE
zVCbljKVP-JgA6<-&lj%i^FE|+#^ktRzGdbPCD~jh_Q?HkPIX@ST)?$PA4EPeA59_~*c774QeO+hx4gv*p
zgRm0d7T&uv7<%yvaW_Ynb9WDaenNsxUYQ%L`?<%wLv1Jqap$L`STPZ7DChRtS~vKbtm1w8ngY
zr2*B;aXKY><39TNmFt$=cGnK;Tv{s*fM7~AoE9Xx91eCNp0L#qh24jR9XxLM8WO#y
zjmDo_C^c~pQvI1>gCN`^@%L;Y{vI7ew&M99f@9m~kGIj^0gqxHp03Msdyntv|NVtk
zC~3|-31k+rIH|o|z+-p+rW9QDs5sv_LRJYCQHU@T;=nRlBH-=q;fT0N@>!~in;XMv
zFt64J1>ik*&}}SEVQun*TfoAsA&Lbk^P3+1@E(i4^5&uc|6q#3nH?v5Kh=WbFVGIe
z@a%WDig}
zzAzws*X8j@+i?Pc88T=B|9FoPucv=NUGv(CsV8Q{!yO;uUkcPGq4YDDWh2r9p{Kk^D`RMeikZxQm*_{o><0R6Q%%Ivl(NMG``IcNuB
zGBz`jQWjUrVxu9Qk=E)wgD~&0ctNX$x)|$AFPlsmC2x6#C)rlAWagTT6v1NdXq4Cs
ztXWf&F99H9R33W{*LDnUy|A;Coo$uBj-0Qqve!&r9YBMJ4)J`WOulF?B^xVpV5%k`
z8)uGdfmxElHa6WxHp_u=v(`iIDma6t&FyO-KjY_@r4-tvVn2os2@WPaTbYtk*t-A16c@96v;ZKcu-t!>&|)0{Vu}G86)rR5znH@452n~~ztoUF
zJ~a3m^!86o(fkigAqK=09{ACjKul5l2UB#GaAn7Jz!)`}R%}(2yVAW3t|RK%^`$M8
z12IK65K~x(`t?!+F~!3h5L1|VJ4;N!)v*961wcWWd+|S*q6vs8O185MMP)!2{;C#gma
z+AwWhrvZqLP}DuQA96TPuzlnn$6Rpf`6=9)9=Kc0=^!1U(fE^s;{vuBcHF{jiMn4~
z2}Dn`!X_(u*P&vYX8_jQpseA`LbcrCQ3h4y(ZZqy3&&+&(yucVt|49L$O6HwQ@YC0
zXj0KWIQ&-D25q`-fGi0sW=@@JKjF>tD@W9oIZ_x0c+cf&v@Lc`n&JxzPqBP!G
zq38f2x!;+{)qI?3idBWGcHP|R03cEpYQf*QdrP4;O^}N}RBylXknhDpeFX70-s_{h
zC)-HbRIaPnMpi4|vcK#0@!w{F!ggvNI{K@TQwL(%l=rqjH5~GzzC&aBi;hIcec$vM
z_^Nix`fZ3oUgEVi;N%X!Bb#JtF{me3iZ~GvArmDwe_lp5*NIRdg~TWNTCa|{MAPL9
zu4y1}lHG?v{9J;_nmuXyXgt`DP3(s!r_1Xlj8VlA!1$I=N(lA|mwQSOf?7%G|FJD966?V!f!@3=%n2kwgwz
zq^Ssvux?P=oEK7Y8ls%L1};PWn`uLSD(_EKe71h*UcTBiP#!y5rakCYzBajIz`b>{
z#jvA_{-=+&5UN^Ei>uxrZb|xAuH5VZ?o9TFh@vfa@3nYB{{>+mAD$(xt?Jldo8f7xmIXCJq!_FY;vJ)E0j;OpeYee@xb0H1WV-CX
zF_~2GFL2YyVU@8_%Zg>Q+!CdlbkH9>UvM;;n17{HpB*GKr9y?f4z*44!uEPSfTN9NQL@96>8vk}k;Wb=}6#ihP(O{HxmiV?0>HWy8`$bt+s1Y#kdz<#Cp_Z4nINTZkl>LZsXlhncX>mVe(-BJ=VjQlB1Ezo)<Xco|>^Ep=?+2v~cN&A=sB1`5ngtg%!;S0!cc$h;;Cr8a}5J_nA
zNK`1GrUvtqmFn7bGrPCyNa?jK9D{_CcIbtAX%2foOK+tez!84{gb>brjV^MGF23};
z5ylCRR`Vau!lOK%SsHUs757e7^Y7>9zN}G9&0URe$gSFttIkbh)Eq%)Op%K*wS6rZ4pQqGLMe
zBw_t>rf2wr&m4XkR2f(t@3peo=C2A>`I9Ucs8tCoWQCf}`I8nPBi8qPB9pk<)BTGo
z@RmDmu75OV{}WZbC`8rJ@7lBgQH4cU7yu-!fOu#aGy3flYHA=5RdB1sCzx-42cim}
zoN*H%s(AOMl4&gS-5$q(RH2g=f;Snzg-5k~G2D=rvL9eEGHV8)1m2Lyt$T2=d>
zY(mH?j(cGU=wq!>(iK2>w!Gc|ydMjTO)DuRKmAZ;)y
z4h8azVx5sT1QW6m=@?_Zp`*NW0>#x=RK@|kNh-%XD4Mz3U>&ErbQ?JO$li`P5cYpH~<
zbFL-aM`thUApln)Hp$_VCvbu9{VeU-%qk;@wQF6bxD-D-(b!$ar~bHZaZGHUrb<+)
zFujZSJ5n&Yzf!Sf8$jR`i{hC@pr%-a#6w4*(J{jeOhuYuyms~<+}}{4XMQ$IoI*^6
zWUk-_zwY3ZBidH_l|IN8sM5?7)rvMat7xx!b=9F&11Q;2-?u$b!eg##$rwtnxNr!g
zSDKYBIajmZr}{vjy&Q_<#OG&!yO#;g0G}7KTgh~cX`I%5NGNNFV8L11EP@|cD-C&Wc{Vk9y~WWvPO
z_^zL_0J3^%oUv*m#_Jq|GsoS0RX0yE0K%fGvIjB9+7b&kalcD@9uzOIOfDVixiUH$
z4OJ&`L%!)aE7V>v9?=Xm{C1BX(cTxyxPF8fq?eILSrJ$vlN1d)g>NEPMo!HA&X<5A
z@--T`A$!^Xf`r@$-??CAz+4>vEjYUf1cqo=62Q(NQa?a4!MXtf@M$j$k0L9v$FmFiDD@3I>KH7tAFoL_5Z_&`?u`#dLSSG
z|EKJY;<-mfRmxVO;~WwF|F`V>Nhm-6i$}!3$NU-B;>?gWFAL=dwj^#PI{oNza-FgD
zeSg14{f?7jA`+K?I2;ruDFZ1PAD1#0VZk^l0c3I`vk6PU6o#orU5SxitU%obkctnKPDA>-MmL0At1aApg$y`{1?cX>y95xX|c_HWDSreNW#;yt=tDhoJt%5n20%vRjUQqYytie;8
zzov9(^`(@@P|KX!*I8=j7(}Q1>-%MMK>ZDE{(L`_6|0Zo<5KcD8USjM-)bexIih(|
z^Csi6bnN+*uyAMt=%d=e(qHQSRTi0zl<&Nl^EZ<*D$;FsB|>P#7a^_@SBEi##H46^
zmqxfOBc!-FV2(1-HdW{RYeB4ZZ{H+;!CqG-B-v_HrRSk?pKs+ITS|>Jnp@7AP_|X@
zBlm4uyxJmZuCg0&YJNT)p~~h4
diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java index 75859b3c3f..b70c5da399 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AbstractDependencyManager.java @@ -17,23 +17,19 @@ */ package org.jackhuang.hmcl.download; -import java.util.List; - /** * * @author huangyuhui */ public abstract class AbstractDependencyManager implements DependencyManager { - public abstract DownloadProvider getPrimaryDownloadProvider(); - - public abstract List getPreferredDownloadProviders(); + public abstract DownloadProvider getDownloadProvider(); @Override public abstract DefaultCacheRepository getCacheRepository(); @Override public VersionList getVersionList(String id) { - return getPrimaryDownloadProvider().getVersionListById(id); + return getDownloadProvider().getVersionListById(id); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java new file mode 100644 index 0000000000..e6d0012946 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java @@ -0,0 +1,81 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.download; + +import org.jackhuang.hmcl.util.io.NetworkUtils; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * The download provider that changes the real download source in need. + * + * @author huangyuhui + */ +public class AdaptedDownloadProvider implements DownloadProvider { + + private List downloadProviderCandidates; + + public void setDownloadProviderCandidates(List downloadProviderCandidates) { + this.downloadProviderCandidates = new ArrayList<>(downloadProviderCandidates); + } + + public DownloadProvider getPreferredDownloadProvider() { + List d = downloadProviderCandidates; + if (d == null || d.isEmpty()) { + throw new IllegalStateException("No download provider candidate"); + } + return d.get(0); + } + + @Override + public String getVersionListURL() { + return getPreferredDownloadProvider().getVersionListURL(); + } + + @Override + public String getAssetBaseURL() { + return getPreferredDownloadProvider().getAssetBaseURL(); + } + + @Override + public String injectURL(String baseURL) { + return getPreferredDownloadProvider().injectURL(baseURL); + } + + @Override + public List injectURLWithCandidates(String baseURL) { + List d = downloadProviderCandidates; + List results = new ArrayList<>(d.size()); + for (int i = 0; i < d.size(); i++) { + results.add(NetworkUtils.toURL(d.get(i).injectURL(baseURL))); + } + return results; + } + + @Override + public VersionList getVersionListById(String id) { + return getPreferredDownloadProvider().getVersionListById(id); + } + + @Override + public int getConcurrency() { + return getPreferredDownloadProvider().getConcurrency(); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 1c58e545e7..7a54c11e64 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.List; /** * Note: This class has no state. @@ -39,13 +38,11 @@ public class DefaultDependencyManager extends AbstractDependencyManager { private final DefaultGameRepository repository; private final DownloadProvider downloadProvider; - private final List preferredDownloadProviders; private final DefaultCacheRepository cacheRepository; - public DefaultDependencyManager(DefaultGameRepository repository, DownloadProvider downloadProvider, List preferredDownloadProviders, DefaultCacheRepository cacheRepository) { + public DefaultDependencyManager(DefaultGameRepository repository, DownloadProvider downloadProvider, DefaultCacheRepository cacheRepository) { this.repository = repository; this.downloadProvider = downloadProvider; - this.preferredDownloadProviders = preferredDownloadProviders; this.cacheRepository = cacheRepository; } @@ -55,15 +52,10 @@ public DefaultGameRepository getGameRepository() { } @Override - public DownloadProvider getPrimaryDownloadProvider() { + public DownloadProvider getDownloadProvider() { return downloadProvider; } - @Override - public List getPreferredDownloadProviders() { - return preferredDownloadProviders; - } - @Override public DefaultCacheRepository getCacheRepository() { return cacheRepository; 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 32240ed6ef..09c8bafedd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -32,21 +32,15 @@ public class DefaultGameBuilder extends GameBuilder { private final DefaultDependencyManager dependencyManager; - private final DownloadProvider downloadProvider; public DefaultGameBuilder(DefaultDependencyManager dependencyManager) { this.dependencyManager = dependencyManager; - this.downloadProvider = dependencyManager.getPrimaryDownloadProvider(); } public DefaultDependencyManager getDependencyManager() { return dependencyManager; } - public DownloadProvider getDownloadProvider() { - return downloadProvider; - } - @Override public Task buildAsync() { List stages = new ArrayList<>(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java index 4229a33342..7ef333044c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java @@ -17,6 +17,13 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.util.io.NetworkUtils; + +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + /** * The service provider that provides Minecraft online file downloads. * @@ -28,6 +35,10 @@ public interface DownloadProvider { String getAssetBaseURL(); + default List getAssetObjectCandidates(String assetObjectLocation) { + return Collections.singletonList(NetworkUtils.toURL(getAssetBaseURL() + assetObjectLocation)); + } + /** * Inject into original URL provided by Mojang and Forge. * @@ -40,9 +51,26 @@ public interface DownloadProvider { String injectURL(String baseURL); /** - * the specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine" + * Inject into original URL provided by Mojang and Forge. + * + * Since there are many provided URLs that are written in JSONs and are unmodifiable, + * this method provides a way to change them. + * + * @param baseURL original URL provided by Mojang and Forge. + * @return the URL that is equivalent to [baseURL], but belongs to your own service provider. + */ + default List injectURLWithCandidates(String baseURL) { + return Collections.singletonList(NetworkUtils.toURL(baseURL)); + } + + default List injectURLsWithCandidates(List urls) { + return urls.stream().flatMap(url -> injectURLWithCandidates(url).stream()).collect(Collectors.toList()); + } + + /** + * the specific version list that this download provider provides. i.e. "fabric", "forge", "liteloader", "game", "optifine" * - * @param id the id of specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine" + * @param id the id of specific version list that this download provider provides. i.e. "fabric", "forge", "liteloader", "game", "optifine" * @return the version list * @throws IllegalArgumentException if the version list does not exist */ diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java index a7d2f7536f..86ed4335a2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java @@ -35,7 +35,7 @@ public class RemoteVersion implements Comparable { private final String libraryId; private final String gameVersion; private final String selfVersion; - private final String[] url; + private final List urls; private final Type type; /** @@ -43,10 +43,10 @@ public class RemoteVersion implements Comparable { * * @param gameVersion the Minecraft version that this remote version suits. * @param selfVersion the version string of the remote version. - * @param url the installer or universal jar URL. + * @param urls the installer or universal jar original URL. */ - public RemoteVersion(String libraryId, String gameVersion, String selfVersion, String... url) { - this(libraryId, gameVersion, selfVersion, Type.UNCATEGORIZED, url); + public RemoteVersion(String libraryId, String gameVersion, String selfVersion, List urls) { + this(libraryId, gameVersion, selfVersion, Type.UNCATEGORIZED, urls); } /** @@ -54,13 +54,13 @@ public RemoteVersion(String libraryId, String gameVersion, String selfVersion, S * * @param gameVersion the Minecraft version that this remote version suits. * @param selfVersion the version string of the remote version. - * @param url the installer or universal jar URL. + * @param urls the installer or universal jar URL. */ - public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Type type, String... url) { + public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Type type, List urls) { this.libraryId = Objects.requireNonNull(libraryId); this.gameVersion = Objects.requireNonNull(gameVersion); this.selfVersion = Objects.requireNonNull(selfVersion); - this.url = Objects.requireNonNull(url); + this.urls = Objects.requireNonNull(urls); this.type = Objects.requireNonNull(type); } @@ -76,8 +76,8 @@ public String getSelfVersion() { return selfVersion; } - public String[] getUrl() { - return url; + public List getUrls() { + return urls; } public Type getVersionType() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java index 275ce04c9e..699ff0155f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java @@ -28,10 +28,8 @@ import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.util.*; -import java.util.stream.Collectors; /** * Note: Fabric should be installed first. @@ -51,9 +49,7 @@ public FabricInstallTask(DefaultDependencyManager dependencyManager, Version ver this.version = version; this.remote = remoteVersion; - launchMetaTask = new GetTask(dependencyManager.getPreferredDownloadProviders().stream() - .map(downloadProvider -> downloadProvider.injectURL(getLaunchMetaUrl(remote.getGameVersion(), remote.getSelfVersion()))) - .map(NetworkUtils::toURL).collect(Collectors.toList())) + launchMetaTask = new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())) .setCacheRepository(dependencyManager.getCacheRepository()); } @@ -90,10 +86,6 @@ public void execute() { dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true)); } - private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { - return String.format("https://meta.fabricmc.net/v2/versions/loader/%s/%s", gameVersion, loaderVersion); - } - private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loaderVersion) { JsonObject launcherMeta = fabricInfo.launcherMeta; Arguments arguments = new Arguments(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java index b9a86cf218..cdac8f2bfd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java @@ -48,7 +48,7 @@ public boolean hasType() { public Task refreshAsync() { return new Task() { @Override - public void execute() throws IOException, XMLStreamException { + public void execute() throws IOException { List gameVersions = getGameVersions(GAME_META_URL); List loaderVersions = getGameVersions(LOADER_META_URL); 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 c66739879f..3ce2ef9983 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 @@ -27,15 +27,15 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.NetworkUtils; -import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; @@ -69,9 +69,7 @@ public void preExecute() throws Exception { installer = Files.createTempFile("forge-installer", ".jar"); dependent = new FileDownloadTask( - dependencyManager.getPreferredDownloadProviders().stream() - .flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL)) - .map(NetworkUtils::toURL).collect(Collectors.toList()), + dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), installer.toFile(), null) .setCacheRepository(dependencyManager.getCacheRepository()) .setCaching(true); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java index 561438fd28..e0a70b7e76 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java @@ -23,15 +23,17 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; +import java.util.List; + public class ForgeRemoteVersion extends RemoteVersion { /** * Constructor. * * @param gameVersion the Minecraft version that this remote version suits. * @param selfVersion the version string of the remote version. - * @param url the installer or universal jar URL. + * @param url the installer or universal jar original URL. */ - public ForgeRemoteVersion(String gameVersion, String selfVersion, String... url) { + public ForgeRemoteVersion(String gameVersion, String selfVersion, List url) { super(LibraryAnalyzer.LibraryType.FORGE.getPatchId(), gameVersion, selfVersion, url); } 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 6f698be2ed..f6b32d62f2 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 @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.game; import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; import org.jackhuang.hmcl.download.AbstractDependencyManager; import org.jackhuang.hmcl.game.AssetIndex; import org.jackhuang.hmcl.game.AssetIndexInfo; @@ -30,7 +29,6 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.File; import java.io.IOException; @@ -39,7 +37,6 @@ import java.util.LinkedList; import java.util.List; import java.util.logging.Level; -import java.util.stream.Collectors; /** * @@ -112,10 +109,7 @@ public void execute() throws Exception { Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + file.toPath(), e); } if (download) { - List urls = dependencyManager.getPreferredDownloadProviders().stream() - .map(downloadProvider -> downloadProvider.getAssetBaseURL() + assetObject.getLocation()) - .map(NetworkUtils::toURL) - .collect(Collectors.toList()); + List urls = dependencyManager.getDownloadProvider().getAssetObjectCandidates(assetObject.getLocation()); FileDownloadTask task = new FileDownloadTask(urls, file, new FileDownloadTask.IntegrityCheck("SHA-1", assetObject.getHash())); task.setName(assetObject.getHash()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index 717bad4f37..3f56f2b5c4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.File; import java.io.IOException; @@ -65,7 +64,7 @@ public void execute() { // We should not check the hash code of asset index file since this file is not consistent // And Mojang will modify this file anytime. So assetIndex.hash might be outdated. dependencies.add(new FileDownloadTask( - NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(assetIndexInfo.getUrl())), + dependencyManager.getDownloadProvider().injectURLWithCandidates(assetIndexInfo.getUrl()), assetIndexFile ).setCacheRepository(dependencyManager.getCacheRepository())); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index f279700c6c..0b906dc54c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -23,13 +23,11 @@ import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.CacheRepository; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.File; import java.util.Collection; import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; /** * Task to download Minecraft jar @@ -59,9 +57,7 @@ public void execute() { File jar = dependencyManager.getGameRepository().getVersionJar(version); FileDownloadTask task = new FileDownloadTask( - dependencyManager.getPreferredDownloadProviders().stream() - .map(downloadProvider -> downloadProvider.injectURL(version.getDownloadInfo().getUrl())) - .map(NetworkUtils::toURL).collect(Collectors.toList()), + dependencyManager.getDownloadProvider().injectURLWithCandidates(version.getDownloadInfo().getUrl()), jar, IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1())) .setCaching(true) 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 6d33a01d4a..1c14d1300e 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 @@ -33,7 +33,7 @@ import java.io.*; import java.net.URL; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -42,7 +42,6 @@ import java.util.jar.JarOutputStream; import java.util.jar.Pack200; import java.util.logging.Level; -import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.DigestUtils.digest; import static org.jackhuang.hmcl.util.Hex.encodeHex; @@ -130,21 +129,15 @@ public void preExecute() throws Exception { } try { - URL packXz = NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(url) + ".pack.xz"); + URL packXz = NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(url) + ".pack.xz"); if (NetworkUtils.urlExists(packXz)) { - List urls = dependencyManager.getPreferredDownloadProviders().stream() - .map(downloadProvider -> downloadProvider.injectURL(url) + ".pack.xz") - .map(NetworkUtils::toURL) - .collect(Collectors.toList()); + List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz"); task = new FileDownloadTask(urls, xzFile, null) .setCacheRepository(cacheRepository) .setCaching(true); xz = true; } else { - List urls = dependencyManager.getPreferredDownloadProviders().stream() - .map(downloadProvider -> downloadProvider.injectURL(url)) - .map(NetworkUtils::toURL) - .collect(Collectors.toList()); + List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url); task = new FileDownloadTask(urls, jar, library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null) .setCacheRepository(cacheRepository) @@ -192,7 +185,7 @@ private static boolean validateJar(byte[] data, List checksums) throws I while (entry != null) { byte[] eData = IOUtils.readFullyWithoutClosing(jar); if (entry.getName().equals("checksums.sha1")) { - hashes = new String(eData, Charset.forName("UTF-8")).split("\n"); + hashes = new String(eData, StandardCharsets.UTF_8).split("\n"); } if (!entry.isDirectory()) { files.put(entry.getName(), encodeHex(digest("SHA-1", eData))); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index af4eaad187..8eb1ebddd4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -22,14 +22,11 @@ import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.IOException; -import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; /** * @@ -46,9 +43,8 @@ public VersionJsonDownloadTask(String gameVersion, DefaultDependencyManager depe this.gameVersion = gameVersion; this.dependencyManager = dependencyManager; this.gameVersionList = dependencyManager.getVersionList("game"); - - if (!gameVersionList.isLoaded()) - dependents.add(gameVersionList.refreshAsync()); + + dependents.add(gameVersionList.loadAsync()); setSignificance(TaskSignificance.MODERATE); } @@ -67,10 +63,6 @@ public Collection> getDependents() { public void execute() throws IOException { RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion) .orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository")); - dependencies.add(new GetTask( - dependencyManager.getPreferredDownloadProviders().stream() - .flatMap(downloadProvider -> Arrays.stream(remoteVersion.getUrl()).map(downloadProvider::injectURL)) - .map(NetworkUtils::toURL).collect(Collectors.toList()) - ).storeTo(this::setResult)); + dependencies.add(new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())).storeTo(this::setResult)); } } 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 cc57671225..430b057a59 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 @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.SystemUtils; import org.jenkinsci.constant_pool_scanner.ConstantPool; @@ -96,9 +95,7 @@ public void preExecute() throws Exception { if (installer == null) { dependents.add(new FileDownloadTask( - dependencyManager.getPreferredDownloadProviders().stream() - .flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL)) - .map(NetworkUtils::toURL).collect(Collectors.toList()), + dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), dest.toFile(), null) .setCacheRepository(dependencyManager.getCacheRepository()) .setCaching(true)); 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 ff2bc4114c..fbe4e5c0c5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -119,6 +119,15 @@ public FileDownloadTask(URL url, File file, IntegrityCheck integrityCheck, int r this(Collections.singletonList(url), file, integrityCheck, retry); } + /** + * Constructor. + * @param urls urls of remote file, will be attempted in order. + * @param file the location that download to. + */ + public FileDownloadTask(List urls, File file) { + this(urls, file, null); + } + /** * Constructor. * @param urls urls of remote file, will be attempted in order. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java index 7ae2371b80..a0541eab98 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/ExtendedProperties.java @@ -17,7 +17,12 @@ */ package org.jackhuang.hmcl.util.javafx; -import static org.jackhuang.hmcl.util.Pair.pair; +import javafx.beans.InvalidationListener; +import javafx.beans.WeakInvalidationListener; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.Property; +import javafx.collections.ObservableList; +import javafx.scene.control.*; import java.util.Objects; import java.util.Optional; @@ -25,16 +30,7 @@ import java.util.function.Consumer; import java.util.function.Function; -import javafx.beans.InvalidationListener; -import javafx.beans.WeakInvalidationListener; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.Property; -import javafx.collections.ObservableList; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ComboBox; -import javafx.scene.control.SelectionModel; -import javafx.scene.control.Toggle; -import javafx.scene.control.ToggleGroup; +import static org.jackhuang.hmcl.util.Pair.pair; /** * @author yushijinhun @@ -126,7 +122,7 @@ private static ObjectProperty createMappedPropertyForToggleGroup(ToggleGr // ==== CheckBox ==== @SuppressWarnings("unchecked") - public static ObjectProperty reservedSelectedPropertyFor(CheckBox checkbox) { + public static ObjectProperty reversedSelectedPropertyFor(CheckBox checkbox) { return (ObjectProperty) checkbox.getProperties().computeIfAbsent( PROP_PREFIX + ".checkbox.reservedSelected", any -> new MappedProperty(checkbox, "ext.reservedSelected", From 3082e4cd162417bb2add3ea9f0e4f993ac18a902 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 12 Apr 2020 14:15:27 +0800 Subject: [PATCH 0331/2639] fix: not downloading assets --- .../hmcl/ui/download/InstallerWizardDownloadProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardDownloadProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardDownloadProvider.java index 22be7f19bc..9aaa9c60a2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardDownloadProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardDownloadProvider.java @@ -47,7 +47,7 @@ public String getAssetBaseURL() { @Override public List getAssetObjectCandidates(String assetObjectLocation) { - return fallback.injectURLWithCandidates(assetObjectLocation); + return fallback.getAssetObjectCandidates(assetObjectLocation); } @Override From feb30a734987118bed388862bf6e3cc8dd6e0221 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 12 Apr 2020 14:16:09 +0800 Subject: [PATCH 0332/2639] fix: wrongly considering Forge 1.12.2 not compatible with OptiFine --- .../hmcl/download/forge/ForgeInstallTask.java | 16 +++++++++++++++- .../hmcl/download/forge/ForgeNewInstallTask.java | 4 ---- 2 files changed, 15 insertions(+), 5 deletions(-) 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 3ce2ef9983..082f3b613c 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 @@ -20,6 +20,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DependencyManager; import org.jackhuang.hmcl.download.VersionMismatchException; +import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.GameVersion; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; @@ -27,6 +28,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.io.IOException; import java.nio.file.FileSystem; @@ -97,7 +99,19 @@ public Collection> getDependencies() { } @Override - public void execute() throws IOException, VersionMismatchException { + public void execute() throws IOException, VersionMismatchException, OptiFineInstallTask.UnsupportedOptiFineInstallationException { + String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); + if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) { + // Forge 1.13 is not compatible with any other libraries. + if (!"net.minecraft.client.main.Main".equals(originalMainClass) && !"cpw.mods.modlauncher.Launcher".equals(originalMainClass)) + throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); + } else { + // Forge 1.12 and older versions is compatible with vanilla and launchwrapper. + // if (!"net.minecraft.client.main.Main".equals(originalMainClass) && !"net.minecraft.launchwrapper.Launch".equals(originalMainClass)) + // throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); + } + + if (detectForgeInstallerType(dependencyManager, version, installer)) dependency = new ForgeNewInstallTask(dependencyManager, version, remote.getSelfVersion(), installer); else diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index aae2b35e1f..d5f33aab29 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -131,10 +131,6 @@ public void preExecute() throws Exception { @Override public void execute() throws Exception { - String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); - if (!"net.minecraft.client.main.Main".equals(originalMainClass) && !"cpw.mods.modlauncher.Launcher".equals(originalMainClass)) - throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); - Path temp = Files.createTempDirectory("forge_installer"); int finished = 0; try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { From 0d59e52ff9ce8397cb223fa27f767ffd1a467191 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 12 Apr 2020 16:52:06 +0800 Subject: [PATCH 0333/2639] fix: prelaunch command not tokenized --- .../main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index f4c52d83d9..f2d717cd05 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -292,7 +292,7 @@ public ManagedProcess launch() throws IOException, InterruptedException { .replace("$INST_MC_DIR", repository.getRunDirectory(version.getId()).getAbsolutePath()) .replace("$INST_JAVA", options.getJava().getBinary().toString()); - new ProcessBuilder(preLaunchCommand) + new ProcessBuilder(StringUtils.tokenize(preLaunchCommand)) .directory(runDirectory).start().waitFor(); } From d8b84a25744db78c64406295be9e3912047d4683 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 12 Apr 2020 17:53:13 +0800 Subject: [PATCH 0334/2639] fix: clear in LogWindow broken --- HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java | 1 + 1 file changed, 1 insertion(+) 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 d01ec20775..3f29e594fd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -178,6 +178,7 @@ private void onTerminateGame() { } private void onClear() { + impl.listView.getItems().clear(); logs.clear(); } From 5adbac3cc977c2dbe729801e1c4d795fc3dc5958 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 14 Apr 2020 15:02:52 +0800 Subject: [PATCH 0335/2639] fix: #699 --- .../download/game/LibraryDownloadTask.java | 15 +++++-- .../jackhuang/hmcl/task/FileDownloadTask.java | 42 +++++++++++++------ 2 files changed, 41 insertions(+), 16 deletions(-) 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 1c14d1300e..616e7e62e4 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 @@ -26,6 +26,8 @@ import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -34,13 +36,11 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; +import java.util.jar.*; import java.util.logging.Level; import static org.jackhuang.hmcl.util.DigestUtils.digest; @@ -142,6 +142,13 @@ public void preExecute() throws Exception { library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null) .setCacheRepository(cacheRepository) .setCaching(true); + task.addIntegrityCheckHandler((file, dest) -> { + String ext = FileUtils.getExtension(dest).toLowerCase(); + if (ext.equals("jar")) { + JarFile jarFile = new JarFile(file.toFile()); + jarFile.getManifest(); + } + }); xz = false; } } catch (IOException e) { 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 fbe4e5c0c5..4dc73bb3e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -91,6 +91,7 @@ public void performCheck(MessageDigest digest) throws ChecksumMismatchException private CacheRepository repository = CacheRepository.getInstance(); private RandomAccessFile rFile; private InputStream stream; + private final ArrayList integrityCheckHandlers = new ArrayList<>(); /** * @param url the URL of remote file. @@ -196,6 +197,10 @@ public FileDownloadTask setCacheRepository(CacheRepository repository) { return this; } + public void addIntegrityCheckHandler(IntegrityCheckHandler handler) { + integrityCheckHandlers.add(Objects.requireNonNull(handler)); + } + @Override public void execute() throws Exception { boolean checkETag; @@ -296,23 +301,27 @@ public void execute() throws Exception { closeFiles(); + if (downloaded != contentLength) + throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); + // Restore temp file to original name. if (isCancelled()) { temp.toFile().delete(); break; - } else { - Files.deleteIfExists(file.toPath()); - if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) - throw new IOException("Unable to make parent directory " + file); - try { - FileUtils.moveFile(temp.toFile(), file); - } catch (Exception e) { - throw new IOException("Unable to move temp file from " + temp + " to " + file, e); - } } - if (downloaded != contentLength) - throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); + for (IntegrityCheckHandler handler : integrityCheckHandlers) { + handler.checkIntegrity(temp, file.toPath()); + } + + Files.deleteIfExists(file.toPath()); + if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) + throw new IOException("Unable to make parent directory " + file); + try { + FileUtils.moveFile(temp.toFile(), file); + } catch (Exception e) { + throw new IOException("Unable to move temp file from " + temp + " to " + file, e); + } // Integrity check if (integrityCheck != null) { @@ -375,7 +384,7 @@ public SpeedEvent(Object source, int speed) { /** * Download speed in byte/sec. - * @return + * @return download speed */ public int getSpeed() { return speed; @@ -387,4 +396,13 @@ public String toString() { } } + public interface IntegrityCheckHandler { + /** + * Check whether the file is corrupted or not. + * @param filePath the file locates in (maybe in temp directory) + * @param destinationPath for real file name + * @throws IOException if the file is corrupted + */ + void checkIntegrity(Path filePath, Path destinationPath) throws IOException; + } } From 4382326dec26d28d244aa0f152a32fc54332c1cc Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 14 Apr 2020 15:07:21 +0800 Subject: [PATCH 0336/2639] fix: not closing JarFile --- .../hmcl/download/game/GameLibrariesTask.java | 15 ++++++++++++++- .../hmcl/download/game/LibraryDownloadTask.java | 5 +++-- 2 files changed, 17 insertions(+), 3 deletions(-) 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 8675d1c537..9f51f32dcd 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 @@ -22,12 +22,14 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.LinkedList; import java.util.List; +import java.util.jar.JarFile; import java.util.logging.Level; /** @@ -84,7 +86,18 @@ public void execute() { if (!download && integrityCheck && !library.getDownload().validateChecksum(jar, true)) download = true; if (!download && integrityCheck && library.getChecksums() != null && !library.getChecksums().isEmpty() && - !LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums())) download = true; + !LibraryDownloadTask.checksumValid(file, library.getChecksums())) download = true; + if (!download && integrityCheck) { + String ext = FileUtils.getExtension(file); + if (ext.equals("jar")) { + try (JarFile jarFile = new JarFile(file)) { + jarFile.getManifest(); + } catch (IOException ignored) { + // the Jar file is malformed, so re-download it. + download = true; + } + } + } } catch (IOException e) { Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e); } 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 616e7e62e4..b077df86c8 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 @@ -145,8 +145,9 @@ public void preExecute() throws Exception { task.addIntegrityCheckHandler((file, dest) -> { String ext = FileUtils.getExtension(dest).toLowerCase(); if (ext.equals("jar")) { - JarFile jarFile = new JarFile(file.toFile()); - jarFile.getManifest(); + try (JarFile jarFile = new JarFile(file.toFile())) { + jarFile.getManifest(); + } } }); xz = false; From b04430528ede5daeb3059cf7673e2e939f79bda3 Mon Sep 17 00:00:00 2001 From: The_BadUser Date: Tue, 14 Apr 2020 20:23:53 +0700 Subject: [PATCH 0337/2639] Update I18N_ru.properties --- .../resources/assets/lang/I18N_ru.properties | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index a6c980a758..b0b0e2664d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -1,24 +1,25 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2020 huangyuhui and contributors +# Авторские права (C) 2020 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. +# Эта программа является свободным программным обеспечением: +# вы можете распространять его и/или изменять в соответствии +# с условиями Стандартной общественной лицензии GNU, опубликованной +# Free Software Foundation, либо версия 3 лицензии, или +# (по вашему выбору) любая более поздняя версия. # -# 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. +# Эта программа распространяется в надежде, что она будет полезна, +# но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемой гарантии +# УТВЕРЖДАЮЩАЯ ИЛИ ФИТНЕС ДЛЯ ОСОБЫХ ЦЕЛЕЙ. Смотрите +# GNU General Public License для более подробной информации. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Вы должны были получить копию Стандартной общественной лицензии GNU +# вместе с этой программой. Если нет, см. . # -# Contributors: Botylyov Yury, The_BadUser +# Содействующие: Botylyov Yury, The_BadUser about.copyright=Авторские права -about.copyright.statement=(c) 2020 huangyuhui. +about.copyright.statement=(C) 2020 huangyuhui. about.author=Автор about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=Отдельное спасибо @@ -66,7 +67,7 @@ account.username=Имя пользователя archive.author=Авторы archive.game_version=Игра -archive.name=Никнейм +archive.name=Название archive.version=Версия assets.download=Скачивание активов @@ -144,7 +145,7 @@ install.installer.choose=Выберите версию %s install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft -install.installer.install=Установить %s +install.installer.install=Установка %s install.installer.install_offline=Установить/обновить из файла install.installer.install_offline.extension=Установщик Forge/OptiFine install.installer.install_offline.tooltip=Поддерживает импорт установочных файлов Forge/OptiFine @@ -155,10 +156,10 @@ install.installer.not_installed=%s не установлен install.installer.optifine=OptiFine install.installer.version=%s - версия: %s install.modpack=Установить модпак -install.new_game=Установите новую игру +install.new_game=Установка новой игры install.new_game.already_exists=Эта версия уже существует. install.new_game.current_game_version=Текущая версия игры -install.new_game.malformed=Недопустимое имя +install.new_game.malformed=Недопустимое название install.select=Выберите операцию install.success=установлено успешно @@ -389,7 +390,7 @@ settings.launcher.log.font=Шрифт журналов (logs) settings.launcher.proxy=Прокси settings.launcher.proxy.authentication=Аутентификация прокси settings.launcher.proxy.disable=Использовать прокси системы -settings.launcher.proxy.host=Host +settings.launcher.proxy.host=Хост settings.launcher.proxy.http=HTTP settings.launcher.proxy.password=Пароль settings.launcher.proxy.port=Порт @@ -402,13 +403,13 @@ settings.physical_memory=Размер физической памяти settings.show_log=Показать журналы (logs) settings.tabs.installers=Установщики settings.type=Тип настройки версии -settings.type.global=Глобальные настройки игры (все настройки разделены между играми) -settings.type.global.manage=Глобальные настройки игры -settings.type.global.edit=Настроить глобальные настройки игры -settings.type.special.enable=Включить специальные настройки для этой игры +settings.type.global=Глобальные настройки версии (все настройки разделены между версиями) +settings.type.global.manage=Глобальные настройки версии +settings.type.global.edit=Настроить глобальные настройки версии +settings.type.special.enable=Включить специальные настройки для этой версии -sponsor.bmclapi=Сервисы загрузки предоставляются BMCLAPI и MCBBS. Чтобы узнать подробности нажмите здесь. -sponsor.hmcl=Hello Minecraft! Launcher - это бесплатная пусковая установка Minecraft с открытым исходным кодом, которая позволяет пользователям легко управлять несколькими отдельными установками Minecraft. Мы используем Afdian, чтобы продолжать платить за хостинг и разработку проектов. Чтобы узнать подробности нажмите здесь. +sponsor.bmclapi=Сервисы загрузки предоставляются BMCLAPI и MCBBS. Для подробностей нажмите здесь. +sponsor.hmcl=Hello Minecraft! Launcher - это бесплатный лаунчер Minecraft с открытым исходным кодом, который позволяет пользователям легко управлять несколькими отдельными установками Minecraft. Мы используем Afdian, чтобы продолжать платить за хостинг и разработку проектов. Для подробностей нажмите здесь. update=Обновление лаунчера update.accept=Обновить @@ -426,12 +427,12 @@ update.latest=Это последняя версия. update.no_browser=Не удаётся открыть браузер. Ссылка была скопирована в буфер обмена. Вставьте её в адресную строку браузера для обновления. update.tooltip=Обновить -version=Игры +version=Версии version.cannot_read=Невозможно найти версию игры. Не удаётся продолжить автоустановку. -version.empty=Нет игры +version.empty=Нет установленных version.empty.add=Установить новую версию version.empty.launch=Нет версии для запуска, установите версию на странице списка версий. -version.forbidden_name=Запрещённое имя, не используйте его. +version.forbidden_name=Запрещённое название, не используйте его. version.game.old=Старые version.game.release=Релизы version.game.snapshot=Snapshots @@ -440,19 +441,19 @@ version.launch.test=Проверить игру version.launch_script=Создать скрипт запуска version.launch_script.failed=Невозможно создать скрипт запуска. version.launch_script.save=Сохранить скрипт запуска -version.launch_script.success=Завершено создание скрипта, %s. +version.launch_script.success=Создание скрипта завершено, %s. version.manage=Все версии version.manage.clean=Очистить каталог игры version.manage.clean.tooltip=Очистить журналы, отчёты об ошибках version.manage.manage=Управление версией version.manage.redownload_assets_index=Обновить файлы игровых активов version.manage.remove=Удалить эту версию -version.manage.remove.confirm=Удалить эту версию %s? Эту версию невозможно восстановить снова! -version.manage.remove.confirm.trash=Удалить эту версию %s? Эту версию с именем %s возможно восстановить из корзины системы. +version.manage.remove.confirm=Удалить эту версию %s? Невозможно восстановить снова! +version.manage.remove.confirm.trash=Удалить эту версию %s? %s возможно восстановить из корзины системы. version.manage.remove.confirm.independent=Поскольку эта версия находится в независимом режиме, удаление этой версии также удалит все сохранённые миры, принадлежащие этой версии. Удалить эту версию %s? version.manage.remove_libraries=Удалить файлы библиотеки version.manage.rename=Переименовать эту версию -version.manage.rename.message=Пожалуйста, введите новое имя для этой версии +version.manage.rename.message=Введите новое название для этой версии version.manage.rename.fail=Не удалось переименовать эту версию. version.settings=Настройки version.update=Обновить модпак From 3a7800db61c9fffe6e9072fca83aed48bcb94528 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 00:12:07 +0800 Subject: [PATCH 0338/2639] alt: align titlebar buttons. Mentioned in #701 --- .../hmcl/ui/ToolbarListPageSkin.java | 10 +++++ .../hmcl/ui/decorator/DecoratorSkin.java | 45 ++++++++++--------- HMCL/src/main/resources/assets/css/root.css | 6 ++- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java index ee905d20bd..05f9d57999 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java @@ -93,5 +93,15 @@ public static JFXButton createToolbarButton(String text, SVG.SVGIcon creator, Ru return ret; } + public static JFXButton createDecoratorButton(String tooltip, SVG.SVGIcon creator, Runnable onClick) { + JFXButton ret = new JFXButton(); + ret.getStyleClass().add("jfx-decorator-button"); + ret.textFillProperty().bind(Theme.foregroundFillBinding()); + ret.setGraphic(wrap(creator.createIcon(Theme.foregroundFillBinding(), -1, -1))); + FXUtils.installFastTooltip(ret, tooltip); + ret.setOnMouseClicked(e -> onClick.run()); + return ret; + } + protected abstract List initializeToolbar(T skinnable); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 9073493132..992207d6d4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -216,32 +216,32 @@ private Node createNavBar(Decorator skinnable, boolean titleBarTransparent, doub HBox navLeft = new HBox(); navLeft.setAlignment(Pos.CENTER_LEFT); navLeft.setPadding(new Insets(0, 5, 0, 5)); - { - JFXButton backNavButton = new JFXButton(); - backNavButton.setGraphic(SVG.back(Theme.foregroundFillBinding(), -1, -1)); - backNavButton.getStyleClass().add("jfx-decorator-button"); - backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); - backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty()); - backNavButton.visibleProperty().set(canBack); - - JFXButton closeNavButton = new JFXButton(); + + JFXButton backNavButton = new JFXButton(); + backNavButton.setGraphic(SVG.back(Theme.foregroundFillBinding(), -1, -1)); + backNavButton.getStyleClass().add("jfx-decorator-button"); + backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); + backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty()); + backNavButton.visibleProperty().set(canBack); + + JFXButton closeNavButton = new JFXButton(); + closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); + closeNavButton.getStyleClass().add("jfx-decorator-button"); + closeNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); + closeNavButton.onActionProperty().bind(skinnable.onCloseNavButtonActionProperty()); + + if (canBack) navLeft.getChildren().add(backNavButton); + if (canClose) navLeft.getChildren().add(closeNavButton); + if (showCloseAsHome) + closeNavButton.setGraphic(SVG.home(Theme.foregroundFillBinding(), -1, -1)); + else closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - closeNavButton.getStyleClass().add("jfx-decorator-button"); - closeNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); - closeNavButton.onActionProperty().bind(skinnable.onCloseNavButtonActionProperty()); - - if (canBack) navLeft.getChildren().add(backNavButton); - if (canClose) navLeft.getChildren().add(closeNavButton); - if (showCloseAsHome) - closeNavButton.setGraphic(SVG.home(Theme.foregroundFillBinding(), -1, -1)); - else - closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - } navBar.setLeft(navLeft); BorderPane center = new BorderPane(); if (title != null) { Label titleLabel = new Label(); + BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT); titleLabel.getStyleClass().add("jfx-decorator-title"); if (titleBarTransparent) titleLabel.pseudoClassStateChanged(TRANSPARENT, true); if (!canClose && !canBack) { @@ -250,6 +250,11 @@ private Node createNavBar(Decorator skinnable, boolean titleBarTransparent, doub // we should have width 2 * 10 reduced titleLabel.setPrefWidth(leftPaneWidth - 20); } + if (titleNode != null) { + titleLabel.prefWidthProperty().bind(Bindings.createDoubleBinding(() -> { + return leftPaneWidth - 20 - backNavButton.getWidth() - closeNavButton.getWidth(); + }, backNavButton.widthProperty(), closeNavButton.widthProperty())); + } titleLabel.setText(title); center.setLeft(titleLabel); BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 80104e0717..7569100738 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -367,13 +367,16 @@ .jfx-tool-bar { -fx-font-size: 13.0; - -fx-font-weight: BOLD; -fx-pref-width: 100.0%; -fx-min-height: 40px; -fx-max-height: 40px; -fx-pref-height: 40px; } +.jfx-tool-bar .jfx-decorator-title { + -fx-font-weight: BOLD; +} + .jfx-tool-bar .background { -fx-background-color: -fx-base-color; } @@ -1131,6 +1134,7 @@ .jfx-decorator-tab .tab-container:selected .tab-label { -fx-text-fill: -fx-base-text-fill; + -fx-font-weight: BOLD; } .window { From 3c716ea1703d08519ab943a46d013f36a4c3fc04 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 00:20:22 +0800 Subject: [PATCH 0339/2639] alt: ask user whether continue launching or not if error --- .../main/java/org/jackhuang/hmcl/game/LauncherHelper.java | 6 +++--- HMCL/src/main/resources/assets/lang/I18N.properties | 6 +++--- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 6 +++--- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 6 +++--- 4 files changed, 12 insertions(+), 12 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 9e1b8080b8..cd7191e6e0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -383,13 +383,13 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers setting.getMaxMemory() > 1.5 * 1024) { // 1.5 * 1024 is an inaccurate number. // Actual memory limit depends on operating system and memory. - Controllers.dialog(i18n("launch.advice.too_large_memory_for_32bit"), i18n("message.error"), MessageType.ERROR, onAccept); + Controllers.confirm(i18n("launch.advice.too_large_memory_for_32bit"), i18n("message.error"), onAccept, null); flag = true; } // Cannot allocate too much memory exceeding free space. if (!flag && OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { - Controllers.dialog(i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), i18n("message.error"), MessageType.ERROR, onAccept); + Controllers.confirm(i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY), i18n("message.error"), onAccept, null); flag = true; } @@ -401,7 +401,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers VersionNumber.VERSION_COMPARATOR.compare(it.getVersion(), "1.12.2-14.23.5.2773") < 0); boolean hasLiteLoader = version.getLibraries().stream().anyMatch(it -> it.is("com.mumfrey", "liteloader")); if (hasForge2760 && hasLiteLoader && gameVersion.compareTo(VersionNumber.asVersion("1.12.2")) == 0) { - Controllers.dialog(i18n("launch.advice.forge2760_liteloader"), i18n("message.error"), MessageType.ERROR, onAccept); + Controllers.confirm(i18n("launch.advice.forge2760_liteloader"), i18n("message.error"), onAccept, null); flag = true; } } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 03fdc6aff5..b4751637a3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -168,13 +168,13 @@ lang.default=Use system language launch.advice.corrected=We have already fixed the JVM selection. If you want to keep your choice of Java version, you can disable the Java VM check in game settings. launch.advice.uncorrected=If you are sure that the game can be started normally, you can disable the Java VM check in game settings. launch.advice.different_platform=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. -launch.advice.forge2760_liteloader=Forge 2760 and higher are not compatible with LiteLoader, please consider upgrading Forge to 2773 or later. +launch.advice.forge2760_liteloader=Forge 2760 and higher are not compatible with LiteLoader, please consider upgrading Forge to 2773 or later. Shall we continue launching? launch.advice.java8_1_13=Minecraft 1.13 and later can only run on Java 8 or later. launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 earlier than 1.8.0_51. Please install the latest version of Java 8. launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later versions of Java. launch.advice.newer_java=Java 8 is recommended to make the game faster. For many Minecraft 1.12 of higher, and most mods, Java 8 is required. -launch.advice.not_enough_space=You have allocated too much memory, because the physical memory size is %dMB, your game may crash. The launcher attempt to launch. -launch.advice.too_large_memory_for_32bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game may crash. The maximum memory capacity for 32 bit systems is is 1024MB. The launcher will attempt to launch. +launch.advice.not_enough_space=You have allocated too much memory, because the physical memory size is %dMB, your game may crash. Shall we continue launching? +launch.advice.too_large_memory_for_32bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game may crash. The maximum memory capacity for 32 bit systems is is 1024MB. Shall we continue launching? launch.failed=Unable to launch launch.failed.cannot_create_jvm=Java virtual machine could not be created. Java arguments may cause issues. Please restart without JVM arguments. launch.failed.creating_process=Failed to create process. Check your Java path. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 47dda45af1..932393e175 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -167,13 +167,13 @@ lang.default=使用系統語言 launch.advice.corrected=我們已經修正了問題。如果您確實希望使用您自訂的 Java 虛擬機,您可以在遊戲設定中關閉 Java 虛擬機相容性檢查。 launch.advice.uncorrected=如果您確實希望使用您自訂的 Java 虛擬機,您可以在遊戲設定中關閉 Java 虛擬機相容性檢查。 launch.advice.different_platform=您的系統為 64 位元,但是 Java 是 32 位元,建議您安裝 64 位 Java。 -launch.advice.forge2760_liteloader=Forge 2760 與 LiteLoader 不相容。請刪除 LiteLoader 或者變更 Forge 至 2773 或更新的版本。 +launch.advice.forge2760_liteloader=Forge 2760 與 LiteLoader 不相容。請刪除 LiteLoader 或者變更 Forge 至 2773 或更新的版本。是否繼續啟動? launch.advice.java8_1_13=Minecraft 1.13 只支援 Java 8 或更高版本,請使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低於 1.8.0_51 的 Java 版本可能會導致 Minecraft 1.13 崩潰。建議您到 https://java.com 安裝最新版的 Java 8。 launch.advice.java9=低於 (包含) 1.13 的有安裝 Mod 的 Minecraft 版本不支援 Java 9 或更高版本,請使用 Java 8。 launch.advice.newer_java=偵測到您未使用 Java 8 及更新版本,Java 8 能使遊戲更順暢而且 Minecraft 1.12 及更新版本和很多 Mod 強制需要 Java 8 版本。 -launch.advice.not_enough_space=您設定的記憶體大小過大,由於超過了系統記憶體大小 %dMB,所以可能影響遊戲體驗或無法啟動遊戲。啟動器仍會嘗試啟動。 -launch.advice.too_large_memory_for_32bit=您設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024MB 的值。啟動器仍會嘗試啟動。 +launch.advice.not_enough_space=您設定的記憶體大小過大,由於超過了系統記憶體大小 %dMB,所以可能影響遊戲體驗或無法啟動遊戲。是否繼續啟動? +launch.advice.too_large_memory_for_32bit=您設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024MB 的值。是否繼續啟動? launch.failed=啟動失敗 launch.failed.cannot_create_jvm=偵測到無法建立 Java 虛擬機,可能是 Java 參數有問題。可以在設定中開啟無參數模式啟動。 launch.failed.creating_process=啟動失敗,在建立新處理程序時發生錯誤。可能是 Java 路徑錯誤。 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 ef5cd5b154..9425a90545 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -167,13 +167,13 @@ lang.default=跟随系统语言 launch.advice.corrected=我们已经修复了问题。如果您确实希望使用您自定义的 Java 虚拟机,您可以在游戏设置中关闭 Java 虚拟机兼容性检查。 launch.advice.uncorrected=如果您确实希望使用您自定义的 Java 虚拟机,您可以在游戏设置中关闭 Java 虚拟机兼容性检查。 launch.advice.different_platform=您的系统是 64 位,但是 Java 是 32 位的,建议您安装 64 位 Java。 -launch.advice.forge2760_liteloader=Forge 2760 与 LiteLoader 不兼容。请删除 LiteLoader 或者更换 Forge 至 2773 或更新的版本。 +launch.advice.forge2760_liteloader=Forge 2760 与 LiteLoader 不兼容。请删除 LiteLoader 或者更换 Forge 至 2773 或更新的版本。是否继续启动? launch.advice.java8_1_13=Minecraft 1.13 只支持 Java 8 或更高版本,请使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低于 1.8.0_51 的 Java 版本可能会导致 Minecraft 1.13 崩溃。建议您到 https://java.com 安装最新版的 Java 8。 launch.advice.java9=低于 1.13 的有安装 Mod 的 Minecraft 版本不支持 Java 9 或更高版本,请使用 Java 8。 launch.advice.newer_java=检测到您未使用 Java 8 及更新版本,Java 8 能使游戏更流畅,而且 Minecraft 1.12 及更新版本和很多 Mod 强制需要 Java 8。 -launch.advice.not_enough_space=您设置的内存大小过大,由于超过了系统内存大小 %dMB,所以可能影响游戏体验或无法启动游戏,启动器仍会尝试启动。 -launch.advice.too_large_memory_for_32bit=您设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024MB 或更小,启动器仍会尝试启动。 +launch.advice.not_enough_space=您设置的内存大小过大,由于超过了系统内存大小 %dMB,所以可能影响游戏体验或无法启动游戏。是否继续启动? +launch.advice.too_large_memory_for_32bit=您设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024MB 或更小。是否继续启动? launch.failed=启动失败 launch.failed.cannot_create_jvm=截获到无法创建 Java 虚拟机,可能是 Java 参数有问题,可以在设置中开启无参数模式启动。 launch.failed.creating_process=启动失败,在创建新进程时发生错误,可能是 Java 路径错误。 From 6ca7a8618949ea0477b28de8d8fc21e43a68aca3 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 13:14:16 +0800 Subject: [PATCH 0340/2639] fix: not checking corruption of forge installer --- .../hmcl/download/game/LibraryDownloadTask.java | 8 -------- .../org/jackhuang/hmcl/task/FileDownloadTask.java | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) 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 b077df86c8..58219ca056 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 @@ -142,14 +142,6 @@ public void preExecute() throws Exception { library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null) .setCacheRepository(cacheRepository) .setCaching(true); - task.addIntegrityCheckHandler((file, dest) -> { - String ext = FileUtils.getExtension(dest).toLowerCase(); - if (ext.equals("jar")) { - try (JarFile jarFile = new JarFile(file.toFile())) { - jarFile.getManifest(); - } - } - }); xz = false; } } catch (IOException e) { 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 4dc73bb3e9..7952e6d389 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -31,6 +31,7 @@ import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; @@ -155,6 +156,8 @@ public FileDownloadTask(List urls, File file, IntegrityCheck integrityCheck this.integrityCheck = integrityCheck; this.retry = retry; + this.addIntegrityCheckHandler(ZIP_INTEGRITY_CHECK_HANDLER); + setName(file.getName()); setExecutor(Schedulers.io()); } @@ -254,6 +257,8 @@ public void execute() throws Exception { repeat--; continue; } + } else if (con.getResponseCode() / 100 == 4) { + } else if (con.getResponseCode() / 100 != 2) { throw new ResponseCodeException(url, con.getResponseCode()); } @@ -405,4 +410,13 @@ public interface IntegrityCheckHandler { */ void checkIntegrity(Path filePath, Path destinationPath) throws IOException; } + + public static final IntegrityCheckHandler ZIP_INTEGRITY_CHECK_HANDLER = (filePath, destinationPath) -> { + String ext = FileUtils.getExtension(destinationPath).toLowerCase(); + if (ext.equals("zip") || ext.equals("jar")) { + try (FileSystem ignored = CompressingUtils.createReadOnlyZipFileSystem(filePath)) { + // test for zip format + } + } + }; } From 1c865e3d8d4f9f98145f1063459c9430e9b4a158 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 13:30:17 +0800 Subject: [PATCH 0341/2639] alt: make scrollbar in logwindow more obvous --- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 3 ++- .../hmcl/ui/construct/FloatScrollBarSkin.java | 4 ++-- HMCL/src/main/resources/assets/css/root.css | 20 +++++++++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) 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 3f29e594fd..bbd362f2f1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -150,6 +150,8 @@ public class LogWindowImpl extends Control { private JFXComboBox cboLines = new JFXComboBox<>(); LogWindowImpl() { + getStyleClass().add("log-window"); + boolean flag = false; cboLines.getItems().setAll("500", "2000", "5000"); for (String i : cboLines.getItems()) @@ -280,7 +282,6 @@ protected LogWindowSkin(LogWindowImpl control) { prefWidthProperty().bind(clippedContainer.widthProperty()); } setPadding(new Insets(2)); - getStyleClass().add("log"); setWrapText(true); setGraphic(null); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java index 3438fa11f1..1dfeee6e7d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java @@ -146,13 +146,13 @@ private void setup() { if (scrollBar.getOrientation() == Orientation.HORIZONTAL) { thumb.relocate(0, -5); - thumb.widthProperty().bind(Bindings.max(5, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.widthProperty()))); + thumb.widthProperty().bind(Bindings.max(20, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.widthProperty()))); thumb.setHeight(5); thumb.xProperty().bind(Bindings.subtract(scrollBar.widthProperty(), thumb.widthProperty()).multiply(position)); } else { thumb.relocate(-5, 0); thumb.setWidth(5); - thumb.heightProperty().bind(Bindings.max(5, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.heightProperty()))); + thumb.heightProperty().bind(Bindings.max(20, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.heightProperty()))); thumb.yProperty().bind(Bindings.subtract(scrollBar.heightProperty(), thumb.heightProperty()).multiply(position)); } } diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 7569100738..5c1d9da7f1 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -951,37 +951,41 @@ -fx-text-fill: gray; } -.log { +.log-window .scroll-bar .thumb { + -fx-fill: rgba(0, 0, 0, 0.5); +} + +.log-window .list-cell { -fx-text-fill: black; -fx-border-width: 0 0 1 0; -fx-border-color: #dddddd; } -.log:empty { +.log-window .list-cell:empty { -fx-border-width: 0; } -.log:fatal { +.log-window .list-cell:fatal { -fx-background-color: #F7A699; } -.log:error { +.log-window .list-cell:error { -fx-background-color: #FFCCBB; } -.log:warn { +.log-window .list-cell:warn { -fx-background-color: #FFEECC; } -.log:info { +.log-window .list-cell:info { -fx-background-color: #FFFFFF; } -.log:debug { +.log-window .list-cell:debug { -fx-background-color: #EEE9E0; } -.log:trace { +.log-window .list-cell:trace { -fx-background-color: #EEE9E0; } From 97e8ff91eac257345e035768b0a792e742f4ef69 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 13:31:58 +0800 Subject: [PATCH 0342/2639] alt: print the reason why renaming version failed --- .../hmcl/game/DefaultGameRepository.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) 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 8a1a264075..072a8ee872 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -30,13 +30,16 @@ import org.jackhuang.hmcl.event.RenameVersionEvent; import org.jackhuang.hmcl.mod.ModManager; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -154,28 +157,32 @@ public boolean renameVersion(String from, String to) { try { Version fromVersion = getVersion(from); - File fromDir = getVersionRoot(from); - File toDir = getVersionRoot(to); - if (!fromDir.renameTo(toDir)) - return false; + Path fromDir = getVersionRoot(from).toPath(); + Path toDir = getVersionRoot(to).toPath(); + Files.move(fromDir, toDir); - File toJson = new File(toDir, to + ".json"); - File toJar = new File(toDir, to + ".jar"); + Path fromJson = toDir.resolve(from + ".json"); + Path fromJar = toDir.resolve(from + ".jar"); + Path toJson = toDir.resolve(to + ".json"); + Path toJar = toDir.resolve(to + ".jar"); - if (!new File(toDir, from + ".json").renameTo(toJson) - || !new File(toDir, from + ".jar").renameTo(toJar)) { + try { + Files.move(fromJson, toJson); + Files.move(fromJar, toJar); + } catch (IOException e) { // recovery - toJson.renameTo(new File(toDir, from + ".json")); - toJar.renameTo(new File(toDir, from + ".jar")); - toDir.renameTo(fromDir); - return false; + Lang.ignoringException(() -> Files.move(toJson, fromJson)); + Lang.ignoringException(() -> Files.move(toJar, fromJar)); + Lang.ignoringException(() -> Files.move(toDir, fromDir)); + throw e; } if (fromVersion.getId().equals(fromVersion.getJar())) fromVersion = fromVersion.setJar(null); - FileUtils.writeText(toJson, JsonUtils.GSON.toJson(fromVersion.setId(to))); + FileUtils.writeText(toJson.toFile(), JsonUtils.GSON.toJson(fromVersion.setId(to))); return true; } catch (IOException | JsonParseException | VersionNotFoundException e) { + LOG.log(Level.WARNING, "Unable to rename version " + from + " to " + to, e); return false; } } From f84c4310f92569eef88246f01b9d473418b10162 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 15 Apr 2020 13:46:44 +0800 Subject: [PATCH 0343/2639] alt: do not retry when server respond with 404 --- .../download/AdaptedDownloadProvider.java | 16 +- .../download/forge/ForgeBMCLVersionList.java | 2 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 204 +++++++++--------- 3 files changed, 118 insertions(+), 104 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java index e6d0012946..6f223553f8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java @@ -63,8 +63,20 @@ public String injectURL(String baseURL) { public List injectURLWithCandidates(String baseURL) { List d = downloadProviderCandidates; List results = new ArrayList<>(d.size()); - for (int i = 0; i < d.size(); i++) { - results.add(NetworkUtils.toURL(d.get(i).injectURL(baseURL))); + for (DownloadProvider downloadProvider : d) { + results.add(NetworkUtils.toURL(downloadProvider.injectURL(baseURL))); + } + return results; + } + + @Override + public List injectURLsWithCandidates(List urls) { + List d = downloadProviderCandidates; + List results = new ArrayList<>(d.size()); + for (DownloadProvider downloadProvider : d) { + for (String baseURL : urls) { + results.add(NetworkUtils.toURL(downloadProvider.injectURL(baseURL))); + } } return results; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index dff3038ec2..da6b39aa52 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -88,8 +88,8 @@ public void execute() { + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat(); String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat(); - urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2); urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1); + urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2); urls.add(NetworkUtils.withQuery("https://bmclapi2.bangbang93.com/forge/download", mapOf( pair("mcversion", version.getGameVersion()), pair("version", version.getVersion()), 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 7952e6d389..f89e0ca469 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -227,133 +227,135 @@ public void execute() throws Exception { Exception exception = null; URL failedURL = null; - for (int repeat = 0; repeat < retry * urls.size(); repeat++) { - URL url = urls.get(repeat / retry); - if (isCancelled()) { - break; - } - - Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file); - Path temp = null; - - try { - updateProgress(0); + int repeat = 0; + download: for (URL url : urls) { + for (int retryTime = 0; retryTime < retry; retryTime++) { + if (isCancelled()) { + break download; + } - HttpURLConnection con = NetworkUtils.createConnection(url); - if (checkETag) repository.injectConnection(con); - con = NetworkUtils.resolveConnection(con); + Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file); + Path temp = null; - if (con.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { - // Handle cache - try { - Path cache = repository.getCachedRemoteFile(con); - FileUtils.copyFile(cache.toFile(), file); - return; - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Unable to use cached file, redownload it", e); - repository.removeRemoteEntry(con); - // Now we must reconnect the server since 304 may result in empty content, - // if we want to redownload the file, we must reconnect the server without etag settings. - repeat--; - continue; + try { + updateProgress(0); + + HttpURLConnection con = NetworkUtils.createConnection(url); + if (checkETag) repository.injectConnection(con); + con = NetworkUtils.resolveConnection(con); + + if (con.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { + // Handle cache + try { + Path cache = repository.getCachedRemoteFile(con); + FileUtils.copyFile(cache.toFile(), file); + return; + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to use cached file, redownload it", e); + repository.removeRemoteEntry(con); + // Now we must reconnect the server since 304 may result in empty content, + // if we want to redownload the file, we must reconnect the server without etag settings. + retryTime--; + continue; + } + } else if (con.getResponseCode() / 100 == 4) { + break; // we will not try this URL again + } else if (con.getResponseCode() / 100 != 2) { + throw new ResponseCodeException(url, con.getResponseCode()); } - } else if (con.getResponseCode() / 100 == 4) { - } else if (con.getResponseCode() / 100 != 2) { - throw new ResponseCodeException(url, con.getResponseCode()); - } + int contentLength = con.getContentLength(); + if (contentLength < 0) + throw new IOException("The content length is invalid."); - int contentLength = con.getContentLength(); - if (contentLength < 0) - throw new IOException("The content length is invalid."); + if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) + throw new IOException("Could not make directory " + file.getAbsoluteFile().getParent()); - if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) - throw new IOException("Could not make directory " + file.getAbsoluteFile().getParent()); + temp = Files.createTempFile(null, null); + rFile = new RandomAccessFile(temp.toFile(), "rw"); - temp = Files.createTempFile(null, null); - rFile = new RandomAccessFile(temp.toFile(), "rw"); + MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest(); - MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest(); + stream = con.getInputStream(); + int lastDownloaded = 0, downloaded = 0; + byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; + while (true) { + if (isCancelled()) { + break; + } - stream = con.getInputStream(); - int lastDownloaded = 0, downloaded = 0; - byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; - while (true) { - if (isCancelled()) { - break; - } + int read = stream.read(buffer); + if (read == -1) + break; - int read = stream.read(buffer); - if (read == -1) - break; + if (digest != null) { + digest.update(buffer, 0, read); + } - if (digest != null) { - digest.update(buffer, 0, read); - } + // Write buffer to file. + rFile.write(buffer, 0, read); + downloaded += read; - // Write buffer to file. - rFile.write(buffer, 0, read); - downloaded += read; + // Update progress information per second + updateProgress(downloaded, contentLength); - // Update progress information per second - updateProgress(downloaded, contentLength); + updateDownloadSpeed(downloaded - lastDownloaded); + lastDownloaded = downloaded; + } updateDownloadSpeed(downloaded - lastDownloaded); - lastDownloaded = downloaded; - } - updateDownloadSpeed(downloaded - lastDownloaded); + closeFiles(); - closeFiles(); + if (downloaded != contentLength) + throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); - if (downloaded != contentLength) - throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); + // Restore temp file to original name. + if (isCancelled()) { + temp.toFile().delete(); + break download; + } - // Restore temp file to original name. - if (isCancelled()) { - temp.toFile().delete(); - break; - } + for (IntegrityCheckHandler handler : integrityCheckHandlers) { + handler.checkIntegrity(temp, file.toPath()); + } - for (IntegrityCheckHandler handler : integrityCheckHandlers) { - handler.checkIntegrity(temp, file.toPath()); - } + Files.deleteIfExists(file.toPath()); + if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) + throw new IOException("Unable to make parent directory " + file); + try { + FileUtils.moveFile(temp.toFile(), file); + } catch (Exception e) { + throw new IOException("Unable to move temp file from " + temp + " to " + file, e); + } - Files.deleteIfExists(file.toPath()); - if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) - throw new IOException("Unable to make parent directory " + file); - try { - FileUtils.moveFile(temp.toFile(), file); - } catch (Exception e) { - throw new IOException("Unable to move temp file from " + temp + " to " + file, e); - } + // Integrity check + if (integrityCheck != null) { + integrityCheck.performCheck(digest); + } - // Integrity check - if (integrityCheck != null) { - integrityCheck.performCheck(digest); - } + if (caching && integrityCheck != null) { + try { + repository.cacheFile(file.toPath(), integrityCheck.getAlgorithm(), integrityCheck.getChecksum()); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Failed to cache file", e); + } + } - if (caching && integrityCheck != null) { - try { - repository.cacheFile(file.toPath(), integrityCheck.getAlgorithm(), integrityCheck.getChecksum()); - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Failed to cache file", e); + if (checkETag) { + repository.cacheRemoteFile(file.toPath(), con); } - } - if (checkETag) { - repository.cacheRemoteFile(file.toPath(), con); + return; + } catch (IOException e) { + if (temp != null) + temp.toFile().delete(); + failedURL = url; + exception = e; + Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (++repeat), e); + } finally { + closeFiles(); } - - return; - } catch (IOException e) { - if (temp != null) - temp.toFile().delete(); - failedURL = url; - exception = e; - Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (repeat + 1), e); - } finally { - closeFiles(); } } From 1eeba344f7d34b29a6742050e1b7cb04de34cae5 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 00:15:34 +0800 Subject: [PATCH 0344/2639] fix: game is blocked for launching --- HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java | 1 - .../src/main/java/org/jackhuang/hmcl/task/Schedulers.java | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 568bb4e099..8762f610d0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -106,7 +106,6 @@ public static void stopApplication() { Schedulers.shutdown(); Controllers.shutdown(); Platform.exit(); - 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 b1bd28c76b..d8397207b4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -73,11 +73,15 @@ public static Executor defaultScheduler() { public static synchronized void shutdown() { Logging.LOG.info("Shutting down executor services."); + // shutdownNow will interrupt all threads. + // So when we want to close the app, no threads need to be waited for finish. + // Sometimes it resolves the problem that the app does not exit. + if (CACHED_EXECUTOR != null) - CACHED_EXECUTOR.shutdown(); + CACHED_EXECUTOR.shutdownNow(); if (IO_EXECUTOR != null) - IO_EXECUTOR.shutdown(); + IO_EXECUTOR.shutdownNow(); } public static Future schedule(Executor executor, Runnable command) { From 02ce9500206fa5f067b5afa146665bf04ed75674 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 00:16:17 +0800 Subject: [PATCH 0345/2639] alt: allow dragging window when a dialog is shown --- .../hmcl/ui/decorator/Decorator.java | 11 +++--- .../ui/decorator/DecoratorController.java | 35 ++++++++----------- .../hmcl/ui/decorator/DecoratorSkin.java | 13 ++++++- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java index 99bfa44bca..8ea39fdf69 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui.decorator; +import com.jfoenix.controls.JFXDialog; import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -46,7 +47,7 @@ public class Decorator extends Control { private final BooleanProperty canClose = new SimpleBooleanProperty(false); private final BooleanProperty showCloseAsHome = new SimpleBooleanProperty(false); private final Stage primaryStage; - private StackPane drawerWrapper; + private JFXDialog dialog; public Decorator(Stage primaryStage) { this.primaryStage = primaryStage; @@ -58,12 +59,12 @@ public Stage getPrimaryStage() { return primaryStage; } - public StackPane getDrawerWrapper() { - return drawerWrapper; + public JFXDialog getDialog() { + return dialog; } - void setDrawerWrapper(StackPane drawerWrapper) { - this.drawerWrapper = drawerWrapper; + void setDialog(JFXDialog dialog) { + this.dialog = dialog; } public ObservableList getDrawer() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 203b81f1b0..f6247f57cc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -72,7 +72,6 @@ public class DecoratorController { private final ImageView welcomeView; private final Navigator navigator; - private JFXDialog dialog; private StackContainerPane dialogPane; public DecoratorController(Stage stage, Node mainPage) { @@ -294,23 +293,21 @@ private void onNavigated(Navigator.NavigationEvent event) { public void showDialog(Node node) { FXUtils.checkFxUserThread(); - if (dialog == null) { - if (decorator.getDrawerWrapper() == null) { - // Sometimes showDialog will be invoked before decorator was initialized. - // Keep trying again. - Platform.runLater(() -> showDialog(node)); - return; - } + if (decorator.getDialog() == null) { + // Sometimes showDialog will be invoked before decorator was initialized. + // Keep trying again. + Platform.runLater(() -> showDialog(node)); + return; + } - dialog = new JFXDialog(); + if (dialogPane == null) { dialogPane = new StackContainerPane(); - - dialog.setContent(dialogPane); - dialog.setDialogContainer(decorator.getDrawerWrapper()); - dialog.setOverlayClose(false); - dialog.show(); + decorator.getDialog().setContent(dialogPane); } + if (dialogPane.isEmpty()) + decorator.getDialog().show(); + dialogPane.push(node); EventHandler handler = event -> closeDialog(node); @@ -319,10 +316,10 @@ public void showDialog(Node node) { if (node instanceof DialogAware) { DialogAware dialogAware = (DialogAware) node; - if (dialog.isVisible()) { + if (decorator.getDialog().isVisible()) { dialogAware.onDialogShown(); } else { - dialog.visibleProperty().addListener(new ChangeListener() { + decorator.getDialog().visibleProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { if (newValue) { @@ -342,13 +339,11 @@ private void closeDialog(Node node) { Optional.ofNullable(node.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER)) .ifPresent(handler -> node.removeEventHandler(DialogCloseEvent.CLOSE, (EventHandler) handler)); - if (dialog != null) { + if (decorator.getDialog() != null) { dialogPane.pop(node); if (dialogPane.getChildren().isEmpty()) { - dialog.close(); - dialog = null; - dialogPane = null; + decorator.getDialog().close(); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 992207d6d4..db77ec665b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.decorator; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXDialog; import com.jfoenix.svg.SVGGlyph; import javafx.beans.binding.Bindings; import javafx.collections.ListChangeListener; @@ -97,7 +98,17 @@ public DecoratorSkin(Decorator control) { BorderPane root = new BorderPane(); root.getStyleClass().addAll("jfx-decorator"); wrapper.getChildren().setAll(root); - skinnable.setDrawerWrapper(wrapper); + + JFXDialog dialog = new JFXDialog(); + dialog.setDialogContainer(wrapper); + dialog.setOverlayClose(false); + dialog.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove = true); + dialog.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { + if (!isDragging) allowMove = false; + }); + + skinnable.setDialog(dialog); + parent.getChildren().add(wrapper); // center node with a animation layer at bottom, a container layer at middle and a "welcome" layer at top. From 32e9076198af93e7a17622588f50388b2cacf6ad Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 00:49:22 +0800 Subject: [PATCH 0346/2639] fix: not compile --- .../resources/assets/lang/I18N.properties | 4 +-- .../resources/assets/lang/I18N_es.properties | 2 +- .../resources/assets/lang/I18N_ru.properties | 27 ++++++++++--------- .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 11 ++++---- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index b4751637a3..b1358b5d32 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -16,7 +16,7 @@ # along with this program. If not, see . # -# Contributors: dxNeil +# Contributors: dxNeil, machinesmith42 about.copyright=Copyright about.copyright.statement=Copyright (c) 2020 huangyuhui. about.author=Author @@ -464,4 +464,4 @@ version.update=Update modpack wizard.prev=< Prev wizard.failed=Failed wizard.finish=Finish -wizard.next=Next > \ No newline at end of file +wizard.next=Next > diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index e3a5072e59..c29131074e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -443,4 +443,4 @@ version.update=Actualizar modpack wizard.prev=< Prev wizard.failed=Fallo wizard.finish=Acabar -wizard.next=Próx > \ No newline at end of file +wizard.next=Próx > diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index b0b0e2664d..de720a3f56 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -1,20 +1,19 @@ # # Hello Minecraft! Launcher -# Авторские права (C) 2020 huangyuhui и содействующие +# Copyright (C) 2020 huangyuhui and contributors # -# Эта программа является свободным программным обеспечением: -# вы можете распространять его и/или изменять в соответствии -# с условиями Стандартной общественной лицензии GNU, опубликованной -# Free Software Foundation, либо версия 3 лицензии, или -# (по вашему выбору) любая более поздняя версия. +# 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. # -# Эта программа распространяется в надежде, что она будет полезна, -# но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемой гарантии -# УТВЕРЖДАЮЩАЯ ИЛИ ФИТНЕС ДЛЯ ОСОБЫХ ЦЕЛЕЙ. Смотрите -# GNU General Public License для более подробной информации. +# 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. # -# Вы должны были получить копию Стандартной общественной лицензии GNU -# вместе с этой программой. Если нет, см. . +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # # Содействующие: Botylyov Yury, The_BadUser @@ -445,6 +444,10 @@ version.launch_script.success=Создание скрипта завершено version.manage=Все версии version.manage.clean=Очистить каталог игры version.manage.clean.tooltip=Очистить журналы, отчёты об ошибках +version.manage.duplicate=Copy game instance +version.manage.duplicate.duplicate_save=Copy saves +version.manage.duplicate.prompt=Type new version name +version.manage.duplicate.confirm= version.manage.manage=Управление версией version.manage.redownload_assets_index=Обновить файлы игровых активов version.manage.remove=Удалить эту версию diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 932393e175..e2bf3f512b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -16,6 +16,7 @@ # along with this program. If not, see . # +# Contributors: pan93412 about.copyright=著作權 about.copyright.statement=著作權所有 (c) 2020 huangyuhui。 about.author=作者 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 9425a90545..e6b2b639f7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -16,6 +16,7 @@ # along with this program. If not, see . # +# Contributors: huangyuhui about.copyright=版权 about.copyright.statement=版权所有 (c) 2020 huangyuhui. about.author=作者 @@ -378,7 +379,7 @@ settings.icon=游戏图标 settings.launcher=启动器设置 settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库文件放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件 settings.launcher.download_source=下载源 -settings.launcher.enable_game_list=在主页内显示游戏列表 +settings.launcher.enable_game_list=在主页内显示版本列表 settings.launcher.language=语言 settings.launcher.launcher_log.export=导出启动器日志 settings.launcher.launcher_log.export.failed=无法导出日志 @@ -428,8 +429,8 @@ update.tooltip=更新 version=游戏 version.cannot_read=读取游戏版本失败,无法进行自动安装 version.empty=没有游戏版本 -version.empty.add=进入游戏列表安装 -version.empty.launch=没有可启动的游戏,你可以点击左侧游戏栏内的设置按钮进入游戏列表安装游戏 +version.empty.add=进入版本列表安装 +version.empty.launch=没有可启动的游戏,你可以点击左侧游戏栏内的设置按钮进入版本列表安装游戏 version.forbidden_name=此版本名称不受支持,请换一个名字 version.game.old=远古版 version.game.release=稳定版 @@ -440,7 +441,7 @@ version.launch_script=生成启动脚本 version.launch_script.failed=生成启动脚本失败 version.launch_script.save=保存启动脚本 version.launch_script.success=启动脚本已生成完毕:%s -version.manage=游戏列表 +version.manage=版本列表 version.manage.clean=清理游戏目录 version.manage.clean.tooltip=清理 logs, crash-reports version.manage.duplicate=复制游戏实例 @@ -463,4 +464,4 @@ version.update=更新整合包 wizard.prev=< 上一步 wizard.failed=失败 wizard.finish=完成 -wizard.next=下一步 > \ No newline at end of file +wizard.next=下一步 > From 99f42db370dde53278fec0df9e954527b0f4c01e Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 14:17:10 +0800 Subject: [PATCH 0347/2639] fix: fail to update --- .../org/jackhuang/hmcl/download/forge/ForgeInstallTask.java | 3 ++- .../org/jackhuang/hmcl/download/game/LibraryDownloadTask.java | 4 +--- .../main/java/org/jackhuang/hmcl/task/FileDownloadTask.java | 2 -- .../java/org/jackhuang/hmcl/util/io/CompressingUtils.java | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) 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 082f3b613c..5dc7ae8951 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 @@ -52,7 +52,7 @@ public final class ForgeInstallTask extends Task { private final Version version; private Path installer; private final ForgeRemoteVersion remote; - private Task dependent; + private FileDownloadTask dependent; private Task dependency; public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) { @@ -75,6 +75,7 @@ public void preExecute() throws Exception { installer.toFile(), null) .setCacheRepository(dependencyManager.getCacheRepository()) .setCaching(true); + dependent.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); } @Override 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 58219ca056..f50644948a 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 @@ -26,8 +26,6 @@ import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Logging; -import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -36,7 +34,6 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -142,6 +139,7 @@ public void preExecute() throws Exception { library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null) .setCacheRepository(cacheRepository) .setCaching(true); + task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); xz = false; } } catch (IOException e) { 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 f89e0ca469..f72d95bb44 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -156,8 +156,6 @@ public FileDownloadTask(List urls, File file, IntegrityCheck integrityCheck this.integrityCheck = integrityCheck; this.retry = retry; - this.addIntegrityCheckHandler(ZIP_INTEGRITY_CHECK_HANDLER); - setName(file.getName()); setExecutor(Schedulers.io()); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java index 907e2f1e29..265826c829 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java @@ -178,9 +178,9 @@ public static FileSystem createZipFileSystem(Path zipFile, boolean create, boole // Since Java 8 throws ZipError stupidly throw new ZipException(error.getMessage()); } catch (UnsupportedOperationException ex) { - throw new IOException("Not a zip file", ex); + throw new ZipException("Not a zip file"); } catch (FileSystemNotFoundException ex) { - throw new IOException("Java Environment is broken"); + throw new ZipException("Java Environment is broken"); } } From 5893eae87f008f9bd70165040a12dae57ead7f4c Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 23:45:15 +0800 Subject: [PATCH 0348/2639] fix: cannot rename game version sometimes --- .../ui/decorator/DecoratorController.java | 7 +- .../hmcl/ui/versions/WorldListPage.java | 9 +- .../java/org/jackhuang/hmcl/game/World.java | 29 ++++--- .../java/org/jackhuang/hmcl/mod/Datapack.java | 84 ++++++++++--------- .../org/jackhuang/hmcl/mod/ModManager.java | 20 +++-- .../multimc/MultiMCInstanceConfiguration.java | 11 ++- .../multimc/MultiMCModpackInstallTask.java | 30 ++++--- .../hmcl/util/platform/JavaVersion.java | 4 +- 8 files changed, 112 insertions(+), 82 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index f6247f57cc..3f6678b516 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -59,6 +59,7 @@ import java.util.Optional; import java.util.Random; import java.util.logging.Level; +import java.util.stream.Stream; import static java.util.stream.Collectors.toList; import static org.jackhuang.hmcl.setting.ConfigHolder.config; @@ -170,9 +171,9 @@ private Optional randomImageIn(Path imageDir) { } List candidates; - try { - candidates = Files.list(imageDir) - .filter(Files::isRegularFile) + try (Stream stream = Files.list(imageDir)) { + candidates = stream + .filter(Files::isRegularFile) .filter(it -> { String filename = it.getFileName().toString(); return filename.endsWith(".png") || filename.endsWith(".jpg"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 2171369fcb..30ccc54d12 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -43,6 +43,7 @@ import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -69,7 +70,7 @@ public WorldListPage() { } @Override - protected ToolbarListPageSkin createDefaultSkin() { + protected ToolbarListPageSkin createDefaultSkin() { return new WorldListPageSkin(); } @@ -87,7 +88,11 @@ public CompletableFuture refresh() { setLoading(true); return CompletableFuture .runAsync(() -> gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(id)).orElse(null)) - .thenApplyAsync(unused -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) + .thenApplyAsync(unused -> { + try (Stream stream = World.getWorlds(savesDir)) { + return stream.parallel().collect(Collectors.toList()); + } + }) .whenCompleteAsync((result, exception) -> { worlds = result; setLoading(false); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java index e07a42a9d0..c8ef2ebb24 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java @@ -102,10 +102,12 @@ private void loadFromZip() throws IOException { return; } - Path root = Files.list(fs.getPath("/")).filter(Files::isDirectory).findAny() - .orElseThrow(() -> new IOException("Not a valid world zip file")); - fileName = FileUtils.getName(root); - loadFromZipImpl(root); + try (Stream stream = Files.list(fs.getPath("/"))) { + Path root = stream.filter(Files::isDirectory).findAny() + .orElseThrow(() -> new IOException("Not a valid world zip file")); + fileName = FileUtils.getName(root); + loadFromZipImpl(root); + } } } @@ -173,14 +175,16 @@ public void install(Path savesDir, String name) throws IOException { new Unzipper(file, worldDir).unzip(); } else { - List subDirs = Files.list(fs.getPath("/")).collect(Collectors.toList()); - if (subDirs.size() != 1) { - throw new IOException("World zip malformed"); + try (Stream stream = Files.list(fs.getPath("/"))) { + List subDirs = stream.collect(Collectors.toList()); + if (subDirs.size() != 1) { + throw new IOException("World zip malformed"); + } + String subDirectoryName = FileUtils.getName(subDirs.get(0)); + new Unzipper(file, worldDir) + .setSubDirectory("/" + subDirectoryName + "/") + .unzip(); } - String subDirectoryName = FileUtils.getName(subDirs.get(0)); - new Unzipper(file, worldDir) - .setSubDirectory("/" + subDirectoryName + "/") - .unzip(); } } @@ -211,7 +215,7 @@ private static CompoundTag parseLevelDat(Path path) throws IOException { public static Stream getWorlds(Path savesDir) { try { - if (Files.exists(savesDir)) + if (Files.exists(savesDir)) { return Files.list(savesDir).flatMap(world -> { try { return Stream.of(new World(world)); @@ -220,6 +224,7 @@ public static Stream getWorlds(Path savesDir) { return Stream.empty(); } }); + } } catch (IOException e) { Logging.LOG.log(Level.WARNING, "Failed to read saves", e); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java index b6a49d4b09..94709419b5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java @@ -58,13 +58,16 @@ public void installTo(Path worldPath) throws IOException { Set packs = new HashSet<>(); for (Pack pack : info) packs.add(pack.getId()); - if (Files.isDirectory(datapacks)) - for (Path datapack : Files.newDirectoryStream(datapacks)) { - if (Files.isDirectory(datapack) && packs.contains(FileUtils.getName(datapack))) - FileUtils.deleteDirectory(datapack.toFile()); - else if (Files.isRegularFile(datapack) && packs.contains(FileUtils.getNameWithoutExtension(datapack))) - Files.delete(datapack); + if (Files.isDirectory(datapacks)) { + try (DirectoryStream directoryStream = Files.newDirectoryStream(datapacks)) { + for (Path datapack : directoryStream) { + if (Files.isDirectory(datapack) && packs.contains(FileUtils.getName(datapack))) + FileUtils.deleteDirectory(datapack.toFile()); + else if (Files.isRegularFile(datapack) && packs.contains(FileUtils.getNameWithoutExtension(datapack))) + Files.delete(datapack); + } } + } if (isMultiple) { new Unzipper(path, worldPath) @@ -148,46 +151,49 @@ public void loadFromDir() { private void loadFromDir(Path dir) throws IOException { List info = new ArrayList<>(); - if (Files.isDirectory(dir)) - for (Path subDir : Files.newDirectoryStream(dir)) { - if (Files.isDirectory(subDir)) { - Path mcmeta = subDir.resolve("pack.mcmeta"); - Path mcmetaDisabled = subDir.resolve("pack.mcmeta.disabled"); - - if (!Files.exists(mcmeta) && !Files.exists(mcmetaDisabled)) - continue; - - boolean enabled = Files.exists(mcmeta); - - try { - PackMcMeta pack = enabled ? JsonUtils.fromNonNullJson(FileUtils.readText(mcmeta), PackMcMeta.class) - : JsonUtils.fromNonNullJson(FileUtils.readText(mcmetaDisabled), PackMcMeta.class); - info.add(new Pack(enabled ? mcmeta : mcmetaDisabled, FileUtils.getName(subDir), pack.getPackInfo().getDescription(), this)); - } catch (IOException | JsonParseException e) { - Logging.LOG.log(Level.WARNING, "Failed to read datapack " + subDir, e); - } - } else if (Files.isRegularFile(subDir)) { - try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(subDir)) { - Path mcmeta = fs.getPath("pack.mcmeta"); + if (Files.isDirectory(dir)) { + try (DirectoryStream directoryStream = Files.newDirectoryStream(dir)) { + for (Path subDir : directoryStream) { + if (Files.isDirectory(subDir)) { + Path mcmeta = subDir.resolve("pack.mcmeta"); + Path mcmetaDisabled = subDir.resolve("pack.mcmeta.disabled"); - if (!Files.exists(mcmeta)) + if (!Files.exists(mcmeta) && !Files.exists(mcmetaDisabled)) continue; - String name = FileUtils.getName(subDir); - if (name.endsWith(".disabled")) { - name = name.substring(0, name.length() - ".disabled".length()); - } - if (!name.endsWith(".zip")) - continue; - name = StringUtils.substringBeforeLast(name, ".zip"); + boolean enabled = Files.exists(mcmeta); - PackMcMeta pack = JsonUtils.fromNonNullJson(FileUtils.readText(mcmeta), PackMcMeta.class); - info.add(new Pack(subDir, name, pack.getPackInfo().getDescription(), this)); - } catch (IOException | JsonParseException e) { - Logging.LOG.log(Level.WARNING, "Failed to read datapack " + subDir, e); + try { + PackMcMeta pack = enabled ? JsonUtils.fromNonNullJson(FileUtils.readText(mcmeta), PackMcMeta.class) + : JsonUtils.fromNonNullJson(FileUtils.readText(mcmetaDisabled), PackMcMeta.class); + info.add(new Pack(enabled ? mcmeta : mcmetaDisabled, FileUtils.getName(subDir), pack.getPackInfo().getDescription(), this)); + } catch (IOException | JsonParseException e) { + Logging.LOG.log(Level.WARNING, "Failed to read datapack " + subDir, e); + } + } else if (Files.isRegularFile(subDir)) { + try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(subDir)) { + Path mcmeta = fs.getPath("pack.mcmeta"); + + if (!Files.exists(mcmeta)) + continue; + + String name = FileUtils.getName(subDir); + if (name.endsWith(".disabled")) { + name = name.substring(0, name.length() - ".disabled".length()); + } + if (!name.endsWith(".zip")) + continue; + name = StringUtils.substringBeforeLast(name, ".zip"); + + PackMcMeta pack = JsonUtils.fromNonNullJson(FileUtils.readText(mcmeta), PackMcMeta.class); + info.add(new Pack(subDir, name, pack.getPackInfo().getDescription(), this)); + } catch (IOException | JsonParseException e) { + Logging.LOG.log(Level.WARNING, "Failed to read datapack " + subDir, e); + } } } } + } Platform.runLater(() -> this.info.setAll(info)); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java index ee629e2ba5..2a4afef33d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -91,13 +92,18 @@ public ModInfo getModInfo(File modFile) { public void refreshMods() throws IOException { modInfos.clear(); if (Files.isDirectory(getModsDirectory())) { - for (Path subitem : Files.newDirectoryStream(getModsDirectory())) { - if (Files.isDirectory(subitem) && VersionNumber.isIntVersionNumber(FileUtils.getName(subitem))) { - // If the folder name is game version, forge will search mod in this subdirectory - for (Path subsubitem : Files.newDirectoryStream(subitem)) - addModInfo(subsubitem.toFile()); - } else { - addModInfo(subitem.toFile()); + try (DirectoryStream modsDirectoryStream = Files.newDirectoryStream(getModsDirectory())) { + for (Path subitem : modsDirectoryStream) { + if (Files.isDirectory(subitem) && VersionNumber.isIntVersionNumber(FileUtils.getName(subitem))) { + // If the folder name is game version, forge will search mod in this subdirectory + try (DirectoryStream subitemDirectoryStream = Files.newDirectoryStream(subitem)) { + for (Path subsubitem : subitemDirectoryStream) { + addModInfo(subsubitem.toFile()); + } + } + } else { + addModInfo(subitem.toFile()); + } } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java index b9d21f0d9b..0165fcbb20 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.util.Optional; import java.util.Properties; +import java.util.stream.Stream; /** * @@ -334,10 +335,12 @@ private static boolean testPath(Path root) { public static Path getRootPath(Path root) throws IOException { if (testPath(root)) return root; - Path candidate = Files.list(root).filter(Files::isDirectory).findAny() - .orElseThrow(() -> new IOException("Not a valid MultiMC modpack")); - if (testPath(candidate)) return candidate; - throw new IOException("Not a valid MultiMC modpack"); + try (Stream stream = Files.list(root)) { + Path candidate = stream.filter(Files::isDirectory).findAny() + .orElseThrow(() -> new IOException("Not a valid MultiMC modpack")); + if (testPath(candidate)) return candidate; + throw new IOException("Not a valid MultiMC modpack"); + } } public static Modpack readMultiMCModpackManifest(Path modpackFile, Charset encoding) throws IOException { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 4e39b23b6e..f99b890fa9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -36,6 +36,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; @@ -148,22 +149,25 @@ public void execute() throws Exception { Path root = MultiMCInstanceConfiguration.getRootPath(fs.getPath("/")); Path patches = root.resolve("patches"); - if (Files.exists(patches)) - for (Path patchJson : Files.newDirectoryStream(patches)) { - if (patchJson.toString().endsWith(".json")) { - // If json is malformed, we should stop installing this modpack instead of skipping it. - MultiMCInstancePatch multiMCPatch = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(Files.newInputStream(patchJson)), MultiMCInstancePatch.class); - - List arguments = new ArrayList<>(); - for (String arg : multiMCPatch.getTweakers()) { - arguments.add("--tweakClass"); - arguments.add(arg); + if (Files.exists(patches)) { + try (DirectoryStream directoryStream = Files.newDirectoryStream(patches)) { + for (Path patchJson : directoryStream) { + if (patchJson.toString().endsWith(".json")) { + // If json is malformed, we should stop installing this modpack instead of skipping it. + MultiMCInstancePatch multiMCPatch = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(Files.newInputStream(patchJson)), MultiMCInstancePatch.class); + + List arguments = new ArrayList<>(); + for (String arg : multiMCPatch.getTweakers()) { + arguments.add("--tweakClass"); + arguments.add(arg); + } + + Version patch = new Version(multiMCPatch.getName(), multiMCPatch.getVersion(), 1, new Arguments().addGameArguments(arguments), multiMCPatch.getMainClass(), multiMCPatch.getLibraries()); + version = version.addPatch(patch); } - - Version patch = new Version(multiMCPatch.getName(), multiMCPatch.getVersion(), 1, new Arguments().addGameArguments(arguments), multiMCPatch.getMainClass(), multiMCPatch.getLibraries()); - version = version.addPatch(patch); } } + } Path libraries = root.resolve("libraries"); if (Files.exists(libraries)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java index 5198ff914a..aad6e63f57 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java @@ -176,8 +176,8 @@ public static synchronized void initialize() { List javaVersions; - try { - javaVersions = lookupJavas(searchPotentialJavaHomes()); + try (Stream stream = searchPotentialJavaHomes()) { + javaVersions = lookupJavas(stream); } catch (IOException e) { LOG.log(Level.WARNING, "Failed to search Java homes", e); javaVersions = new ArrayList<>(); From 859da37d71d88fbdd7927552e41558dedfd7604b Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 23:46:08 +0800 Subject: [PATCH 0349/2639] fix: not generating modpack.cfg when CurseCompletionTask fail --- .../jackhuang/hmcl/game/HMCLModpackInstallTask.java | 2 +- .../org/jackhuang/hmcl/mod/ModpackInstallTask.java | 3 ++- .../org/jackhuang/hmcl/mod/curse/CurseInstallTask.java | 10 ++++++---- .../hmcl/mod/multimc/MultiMCModpackInstallTask.java | 3 ++- .../hmcl/mod/server/ServerModpackLocalInstallTask.java | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) 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 867ff195e8..3d7e2167b8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -77,6 +77,7 @@ public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, St } catch (JsonParseException | IOException ignore) { } dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/minecraft", it -> !"pack.json".equals(it), config)); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override @@ -104,7 +105,6 @@ public void execute() throws Exception { } dependencies.add(libraryTask.thenComposeAsync(repository::save)); - dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java index cd65274847..d7f7f3b29e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java @@ -89,7 +89,8 @@ public void execute() throws Exception { // If both old and new modpacks have this entry, but the file is deleted by user, leave it missing. return false; } else { - // If user modified this entry file, we will not replace this file since this modified file is that user expects. + // If both old and new modpacks have this entry, and user has modified this file, + // we will not replace it since this modified file is what user expects. String fileHash = encodeHex(digest("SHA-1", Files.newInputStream(destPath))); String oldHash = files.get(entryPath).getHash(); return Objects.equals(oldHash, fileHash); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java index 14a31ee35a..721f25bbf2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java @@ -107,7 +107,9 @@ public CurseInstallTask(DefaultDependencyManager dependencyManager, File zipFile } this.config = config; dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), manifest.getOverrides(), any -> true, config).withStage("hmcl.modpack")); - dependents.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); + + dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download")); } @Override @@ -122,7 +124,8 @@ public Collection> getDependencies() { @Override public void execute() throws Exception { - if (config != null) + if (config != null) { + // For update, remove mods not listed in new manifest for (CurseManifestFile oldCurseManifestFile : config.getManifest().getFiles()) { if (StringUtils.isBlank(oldCurseManifestFile.getFileName())) continue; File oldFile = new File(run, "mods/" + oldCurseManifestFile.getFileName()); @@ -131,11 +134,10 @@ public void execute() throws Exception { if (!oldFile.delete()) throw new IOException("Unable to delete mod file " + oldFile); } + } File root = repository.getVersionRoot(name); FileUtils.writeText(new File(root, "manifest.json"), JsonUtils.GSON.toJson(manifest)); - - dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index f99b890fa9..ea8249d310 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -134,6 +134,8 @@ public void preExecute() throws Exception { else if (Files.exists(fs.getPath("/" + manifest.getName() + "/minecraft"))) dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", any -> true, config).withStage("hmcl.modpack")); } + + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override @@ -179,7 +181,6 @@ public void execute() throws Exception { } dependencies.add(repository.save(version)); - dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java index 6b233de67d..8eefe29e36 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java @@ -82,6 +82,7 @@ public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, } catch (JsonParseException | IOException ignore) { } dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/overrides", any -> true, config).withStage("hmcl.modpack")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override @@ -96,7 +97,6 @@ public List> getDependencies() { @Override public void execute() throws Exception { - dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override From 2701a84b94afbc8c2dfd2287e91e687a0d2e374c Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 17 Apr 2020 23:46:20 +0800 Subject: [PATCH 0350/2639] fix: jfxdialog --- .../hmcl/ui/decorator/Decorator.java | 46 ++++++++++++++++--- .../ui/decorator/DecoratorController.java | 38 ++++++++------- .../hmcl/ui/decorator/DecoratorSkin.java | 24 ++-------- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java index 8ea39fdf69..e33d7ba83f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.decorator; -import com.jfoenix.controls.JFXDialog; import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -26,6 +25,7 @@ import javafx.scene.Node; import javafx.scene.control.Control; import javafx.scene.control.Skin; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.Background; import javafx.scene.layout.StackPane; import javafx.stage.Stage; @@ -47,7 +47,10 @@ public class Decorator extends Control { private final BooleanProperty canClose = new SimpleBooleanProperty(false); private final BooleanProperty showCloseAsHome = new SimpleBooleanProperty(false); private final Stage primaryStage; - private JFXDialog dialog; + private StackPane drawerWrapper; + + private final ReadOnlyBooleanWrapper allowMove = new ReadOnlyBooleanWrapper(); + private final ReadOnlyBooleanWrapper dragging = new ReadOnlyBooleanWrapper(); public Decorator(Stage primaryStage) { this.primaryStage = primaryStage; @@ -59,12 +62,12 @@ public Stage getPrimaryStage() { return primaryStage; } - public JFXDialog getDialog() { - return dialog; + public StackPane getDrawerWrapper() { + return drawerWrapper; } - void setDialog(JFXDialog dialog) { - this.dialog = dialog; + public void setDrawerWrapper(StackPane drawerWrapper) { + this.drawerWrapper = drawerWrapper; } public ObservableList getDrawer() { @@ -167,6 +170,30 @@ public BooleanProperty showCloseAsHomeProperty() { return showCloseAsHome; } + public boolean isAllowMove() { + return allowMove.get(); + } + + public ReadOnlyBooleanProperty allowMoveProperty() { + return allowMove.getReadOnlyProperty(); + } + + void setAllowMove(boolean allowMove) { + this.allowMove.set(allowMove); + } + + public boolean isDragging() { + return dragging.get(); + } + + public ReadOnlyBooleanProperty draggingProperty() { + return dragging.getReadOnlyProperty(); + } + + void setDragging(boolean dragging) { + this.dragging.set(dragging); + } + public ObjectProperty> onBackNavButtonActionProperty() { return onBackNavButtonAction; } @@ -191,4 +218,11 @@ public void minimize() { public void close() { onCloseButtonAction.get().run(); } + + public void capableDraggingWindow(Node node) { + node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove.set(true)); + node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { + if (!isDragging()) allowMove.set(false); + }); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 3f6678b516..7a50d4c55d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -73,6 +73,7 @@ public class DecoratorController { private final ImageView welcomeView; private final Navigator navigator; + private JFXDialog dialog; private StackContainerPane dialogPane; public DecoratorController(Stage stage, Node mainPage) { @@ -294,21 +295,22 @@ private void onNavigated(Navigator.NavigationEvent event) { public void showDialog(Node node) { FXUtils.checkFxUserThread(); - if (decorator.getDialog() == null) { - // Sometimes showDialog will be invoked before decorator was initialized. - // Keep trying again. - Platform.runLater(() -> showDialog(node)); - return; - } - - if (dialogPane == null) { + if (dialog == null) { + if (decorator.getDrawerWrapper() == null) { + // Sometimes showDialog will be invoked before decorator was initialized. + // Keep trying again. + Platform.runLater(() -> showDialog(node)); + return; + } + dialog = new JFXDialog(); dialogPane = new StackContainerPane(); - decorator.getDialog().setContent(dialogPane); - } - - if (dialogPane.isEmpty()) - decorator.getDialog().show(); + dialog.setContent(dialogPane); + decorator.capableDraggingWindow(dialog); + dialog.setDialogContainer(decorator.getDrawerWrapper()); + dialog.setOverlayClose(false); + dialog.show(); + } dialogPane.push(node); EventHandler handler = event -> closeDialog(node); @@ -317,10 +319,10 @@ public void showDialog(Node node) { if (node instanceof DialogAware) { DialogAware dialogAware = (DialogAware) node; - if (decorator.getDialog().isVisible()) { + if (dialog.isVisible()) { dialogAware.onDialogShown(); } else { - decorator.getDialog().visibleProperty().addListener(new ChangeListener() { + dialog.visibleProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { if (newValue) { @@ -340,11 +342,13 @@ private void closeDialog(Node node) { Optional.ofNullable(node.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER)) .ifPresent(handler -> node.removeEventHandler(DialogCloseEvent.CLOSE, (EventHandler) handler)); - if (decorator.getDialog() != null) { + if (dialog != null) { dialogPane.pop(node); if (dialogPane.getChildren().isEmpty()) { - decorator.getDialog().close(); + dialog.close(); + dialog = null; + dialogPane = null; } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index db77ec665b..663fa2a237 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.decorator; import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXDialog; import com.jfoenix.svg.SVGGlyph; import javafx.beans.binding.Bindings; import javafx.collections.ListChangeListener; @@ -58,7 +57,6 @@ public class DecoratorSkin extends SkinBase { private final StackPane leftPane; private double xOffset, yOffset, newX, newY, initX, initY; - private boolean allowMove, isDragging; private boolean titleBarTransparent = true; /** @@ -98,16 +96,7 @@ public DecoratorSkin(Decorator control) { BorderPane root = new BorderPane(); root.getStyleClass().addAll("jfx-decorator"); wrapper.getChildren().setAll(root); - - JFXDialog dialog = new JFXDialog(); - dialog.setDialogContainer(wrapper); - dialog.setOverlayClose(false); - dialog.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove = true); - dialog.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { - if (!isDragging) allowMove = false; - }); - - skinnable.setDialog(dialog); + skinnable.setDrawerWrapper(wrapper); parent.getChildren().add(wrapper); @@ -148,10 +137,7 @@ public DecoratorSkin(Decorator control) { titleContainer = new StackPane(); titleContainer.setPickOnBounds(false); titleContainer.getStyleClass().addAll("jfx-tool-bar"); - titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove = true); - titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { - if (!isDragging) allowMove = false; - }); + control.capableDraggingWindow(titleContainer); StackPane titleBarBackground = new StackPane(); titleBarBackground.getStyleClass().add("background"); @@ -400,11 +386,11 @@ protected void onMouseMoved(MouseEvent mouseEvent) { } protected void onMouseReleased(MouseEvent mouseEvent) { - isDragging = false; + getSkinnable().setDragging(false); } protected void onMouseDragged(MouseEvent mouseEvent) { - this.isDragging = true; + getSkinnable().setDragging(true); if (mouseEvent.isPrimaryButtonDown() && (this.xOffset != -1.0 || this.yOffset != -1.0)) { if (!this.primaryStage.isFullScreen() && !mouseEvent.isStillSincePress()) { this.newX = mouseEvent.getScreenX(); @@ -458,7 +444,7 @@ protected void onMouseDragged(MouseEvent mouseEvent) { } mouseEvent.consume(); - } else if (this.allowMove) { + } else if (getSkinnable().isAllowMove()) { this.primaryStage.setX(mouseEvent.getScreenX() - this.xOffset); this.primaryStage.setY(mouseEvent.getScreenY() - this.yOffset); mouseEvent.consume(); From 0639d8291469f1b6bd710e74931129e1508cca82 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 18 Apr 2020 10:45:39 +0800 Subject: [PATCH 0351/2639] add: launch button in gamelist --- .../org/jackhuang/hmcl/ui/main/RootPage.java | 18 +++++++---- .../hmcl/ui/versions/GameListItemSkin.java | 30 +++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java index 0b69a049e4..2d2558947b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java @@ -200,6 +200,14 @@ public Tab getProfileTab() { return profileTab; } + private void selectPage(Tab tab) { + if (getSelectionModel().getSelectedItem() == tab) { + getSelectionModel().select(getMainTab()); + } else { + getSelectionModel().select(tab); + } + } + private static class Skin extends SkinBase { protected Skin(RootPage control) { @@ -208,7 +216,7 @@ protected Skin(RootPage control) { // first item in left sidebar AccountAdvancedListItem accountListItem = new AccountAdvancedListItem(); accountListItem.activeProperty().bind(control.accountTab.selectedProperty()); - accountListItem.setOnAction(e -> control.getSelectionModel().select(control.accountTab)); + accountListItem.setOnAction(e -> control.selectPage(control.accountTab)); accountListItem.accountProperty().bind(Accounts.selectedAccountProperty()); // second item in left sidebar @@ -218,7 +226,7 @@ protected Skin(RootPage control) { Profile profile = Profiles.getSelectedProfile(); String version = Profiles.getSelectedVersion(); if (version == null) { - control.getSelectionModel().select(control.gameTab); + control.selectPage(control.gameTab); } else { Versions.modifyGameSettings(profile, version); } @@ -229,12 +237,12 @@ protected Skin(RootPage control) { gameItem.activeProperty().bind(control.gameTab.selectedProperty()); gameItem.setImage(newImage("/assets/img/bookshelf.png")); gameItem.setTitle(i18n("version.manage")); - gameItem.setOnAction(e -> control.getSelectionModel().select(control.gameTab)); + gameItem.setOnAction(e -> control.selectPage(control.gameTab)); // forth item in left sidebar ProfileAdvancedListItem profileListItem = new ProfileAdvancedListItem(); profileListItem.activeProperty().bind(control.profileTab.selectedProperty()); - profileListItem.setOnAction(e -> control.getSelectionModel().select(control.profileTab)); + profileListItem.setOnAction(e -> control.selectPage(control.profileTab)); profileListItem.profileProperty().bind(Profiles.selectedProfileProperty()); // fifth item in left sidebar @@ -242,7 +250,7 @@ protected Skin(RootPage control) { launcherSettingsItem.activeProperty().bind(control.settingsTab.selectedProperty()); launcherSettingsItem.setImage(newImage("/assets/img/command.png")); launcherSettingsItem.setTitle(i18n("settings.launcher")); - launcherSettingsItem.setOnAction(e -> control.getSelectionModel().select(control.settingsTab)); + launcherSettingsItem.setOnAction(e -> control.selectPage(control.settingsTab)); // the left sidebar AdvancedListBox sideBar = new AdvancedListBox() diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index d0d2a3c7ad..873bdb5906 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -87,15 +87,27 @@ public GameListItemSkin(GameListItem skinnable) { right.getChildren().add(btnUpgrade); } - JFXButton btnManage = new JFXButton(); - btnManage.setOnMouseClicked(e -> { - currentSkinnable = skinnable; - popup.show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight()); - }); - btnManage.getStyleClass().add("toggle-icon4"); - BorderPane.setAlignment(btnManage, Pos.CENTER); - btnManage.setGraphic(SVG.dotsVertical(Theme.blackFillBinding(), -1, -1)); - right.getChildren().add(btnManage); + { + JFXButton btnLaunch = new JFXButton(); + btnLaunch.setOnMouseClicked(e -> skinnable.launch()); + btnLaunch.getStyleClass().add("toggle-icon4"); + BorderPane.setAlignment(btnLaunch, Pos.CENTER); + btnLaunch.setGraphic(SVG.launch(Theme.blackFillBinding(), 20, 20)); + right.getChildren().add(btnLaunch); + } + + { + JFXButton btnManage = new JFXButton(); + btnManage.setOnMouseClicked(e -> { + currentSkinnable = skinnable; + popup.show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight()); + }); + btnManage.getStyleClass().add("toggle-icon4"); + BorderPane.setAlignment(btnManage, Pos.CENTER); + btnManage.setGraphic(SVG.dotsVertical(Theme.blackFillBinding(), -1, -1)); + right.getChildren().add(btnManage); + } + root.setRight(right); root.getStyleClass().add("card"); From e630c6dff7ef041dac69d4033c4056b3d84a01b2 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 18 Apr 2020 18:57:01 +0800 Subject: [PATCH 0352/2639] fix: downloading libraries of optifine --- .../jackhuang/hmcl/game/LauncherHelper.java | 42 ++++++++------- .../download/DefaultDependencyManager.java | 29 ++++++++++ .../hmcl/download/DependencyManager.java | 10 ++++ .../hmcl/download/LibraryAnalyzer.java | 14 +++-- .../hmcl/download/game/GameLibrariesTask.java | 54 ++++++++++--------- 5 files changed, 97 insertions(+), 52 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 cd7191e6e0..1029729fce 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -126,26 +126,28 @@ private void launch0() { DefaultDependencyManager dependencyManager = profile.getDependency(); Version version = MaintainTask.maintain(repository, repository.getResolvedVersion(selectedVersion)); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); - - TaskExecutor executor = Task.allOf( - Task.composeAsync(() -> { - if (setting.isNotCheckGame()) - return null; - else - return dependencyManager.checkGameCompletionAsync(version, repository.unmarkVersionLaunchedAbnormally(selectedVersion)); - }), Task.composeAsync(() -> { - try { - ModpackConfiguration configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion)); - if ("Curse".equals(configuration.getType())) - return new CurseCompletionTask(dependencyManager, selectedVersion); - else if ("Server".equals(configuration.getType())) - return new ServerModpackCompletionTask(dependencyManager, selectedVersion); - else - return null; - } catch (IOException e) { - return null; - } - })).withStage("launch.state.dependencies") + boolean integrityCheck = repository.unmarkVersionLaunchedAbnormally(selectedVersion); + + TaskExecutor executor = dependencyManager.checkPatchCompletionAsync(repository.getVersion(selectedVersion), integrityCheck) + .thenComposeAsync(Task.allOf( + Task.composeAsync(() -> { + if (setting.isNotCheckGame()) + return null; + else + return dependencyManager.checkGameCompletionAsync(version, integrityCheck); + }), Task.composeAsync(() -> { + try { + ModpackConfiguration configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion)); + if ("Curse".equals(configuration.getType())) + return new CurseCompletionTask(dependencyManager, selectedVersion); + else if ("Server".equals(configuration.getType())) + return new ServerModpackCompletionTask(dependencyManager, selectedVersion); + else + return null; + } catch (IOException e) { + return null; + } + }))).withStage("launch.state.dependencies") .thenComposeAsync(Task.supplyAsync(() -> { try { return account.logIn(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 7a54c11e64..07dbf9dc15 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -23,11 +23,18 @@ import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.DefaultGameRepository; +import org.jackhuang.hmcl.game.GameVersion; +import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.OPTIFINE; /** * Note: This class has no state. @@ -86,6 +93,28 @@ public Task checkLibraryCompletionAsync(Version version, boolean integrityChe return new GameLibrariesTask(this, version, integrityCheck, version.getLibraries()); } + @Override + public Task checkPatchCompletionAsync(Version version, boolean integrityCheck) { + return Task.composeAsync(() -> { + List> tasks = new ArrayList<>(); + + Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); + if (!gameVersion.isPresent()) return null; + + LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(getGameRepository())); + version.resolve(getGameRepository()).getLibraries().stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { + Optional libraryVersion = analyzer.getVersion(OPTIFINE); + if (OPTIFINE.matchLibrary(library) && libraryVersion.isPresent()) { + if (GameLibrariesTask.shouldDownloadLibrary(repository, version, library, integrityCheck)) { + tasks.add(installLibraryAsync(gameVersion.get(), version, OPTIFINE.getPatchId(), libraryVersion.get())); + } + } + }); + + return Task.allOf(tasks); + }); + } + @Override public Task installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion) { if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved"); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java index 5c89edd3c4..c358fabb42 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java @@ -56,6 +56,16 @@ public interface DependencyManager { */ Task checkLibraryCompletionAsync(Version version, boolean integrityCheck); + /** + * Check if patches of this version in complete. + * If not, reinstall the patch if possible. + * + * @param version the version to be checked + * @param integrityCheck check if some libraries are corrupt. + * @return the task to check patches completion. + */ + Task checkPatchCompletionAsync(Version version, boolean integrityCheck); + /** * The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine. */ diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index 2520ac1595..acdb8b2356 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -91,10 +91,7 @@ private Version removingMatchedLibrary(Version version, String libraryId) { List libraries = new ArrayList<>(); for (Library library : version.getLibraries()) { - String groupId = library.getGroupId(); - String artifactId = library.getArtifactId(); - - if (type.group.matcher(groupId).matches() && type.artifact.matcher(artifactId).matches()) { + if (type.matchLibrary(library)) { // skip } else { libraries.add(library); @@ -129,11 +126,8 @@ public static LibraryAnalyzer analyze(Version version) { Map> libraries = new HashMap<>(); for (Library library : version.resolve(null).getLibraries()) { - String groupId = library.getGroupId(); - String artifactId = library.getArtifactId(); - for (LibraryType type : LibraryType.values()) { - if (type.group.matcher(groupId).matches() && type.artifact.matcher(artifactId).matches()) { + if (type.matchLibrary(library)) { libraries.put(type.getPatchId(), pair(library, library.getVersion())); break; } @@ -180,6 +174,10 @@ public static LibraryType fromPatchId(String patchId) { return type; return null; } + + public boolean matchLibrary(Library library) { + return group.matcher(library.getGroupId()).matches() && artifact.matcher(library.getArtifactId()).matches(); + } } public static class LibraryMark { 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 9f51f32dcd..5239598597 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 @@ -18,8 +18,10 @@ package org.jackhuang.hmcl.download.game; import org.jackhuang.hmcl.download.AbstractDependencyManager; +import org.jackhuang.hmcl.game.GameRepository; 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.Logging; import org.jackhuang.hmcl.util.io.FileUtils; @@ -29,7 +31,6 @@ import java.nio.file.Path; import java.util.LinkedList; import java.util.List; -import java.util.jar.JarFile; import java.util.logging.Level; /** @@ -76,33 +77,38 @@ public List> getDependencies() { return dependencies; } - @Override - public void execute() { - libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { - File file = dependencyManager.getGameRepository().getLibraryFile(version, library); - Path jar = file.toPath(); - boolean download = !file.isFile(); - try { - if (!download && integrityCheck && !library.getDownload().validateChecksum(jar, true)) download = true; - if (!download && integrityCheck && - library.getChecksums() != null && !library.getChecksums().isEmpty() && - !LibraryDownloadTask.checksumValid(file, library.getChecksums())) download = true; - if (!download && integrityCheck) { - String ext = FileUtils.getExtension(file); - if (ext.equals("jar")) { - try (JarFile jarFile = new JarFile(file)) { - jarFile.getManifest(); - } catch (IOException ignored) { - // the Jar file is malformed, so re-download it. - download = true; - } + public static boolean shouldDownloadLibrary(GameRepository gameRepository, Version version, Library library, boolean integrityCheck) { + File file = gameRepository.getLibraryFile(version, library); + Path jar = file.toPath(); + if (!file.isFile()) return true; + try { + if (integrityCheck && !library.getDownload().validateChecksum(jar, true)) return true; + if (integrityCheck && + library.getChecksums() != null && !library.getChecksums().isEmpty() && + !LibraryDownloadTask.checksumValid(file, library.getChecksums())) return true; + if (integrityCheck) { + String ext = FileUtils.getExtension(file); + if (ext.equals("jar")) { + try { + FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(jar, jar); + } catch (IOException ignored) { + // the Jar file is malformed, so re-download it. + return true; } } - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e); } + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e); + } + + return false; + } - if (download) { + @Override + public void execute() { + libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { + File file = dependencyManager.getGameRepository().getLibraryFile(version, library); + if (shouldDownloadLibrary(dependencyManager.getGameRepository(), version, library, integrityCheck)) { dependencies.add(new LibraryDownloadTask(dependencyManager, file, library)); } else { dependencyManager.getCacheRepository().tryCacheLibrary(library, file.toPath()); From 62b6c0740179dd5e73978cc8fab68e009074de93 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 22 Apr 2020 23:52:25 +0800 Subject: [PATCH 0353/2639] fix: npe --- .../jackhuang/hmcl/game/LauncherHelper.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 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 1029729fce..e6f09d378f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -91,7 +91,6 @@ public LauncherHelper(Profile profile, Account account, String selectedVersion) } private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(it -> {}); - private CountDownLatch launchingLatch; public void setTestMode() { launcherVisibility = LauncherVisibility.KEEP; @@ -127,6 +126,7 @@ private void launch0() { Version version = MaintainTask.maintain(repository, repository.getResolvedVersion(selectedVersion)); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); boolean integrityCheck = repository.unmarkVersionLaunchedAbnormally(selectedVersion); + CountDownLatch launchingLatch = new CountDownLatch(1); TaskExecutor executor = dependencyManager.checkPatchCompletionAsync(repository.getVersion(selectedVersion), integrityCheck) .thenComposeAsync(Task.allOf( @@ -167,7 +167,7 @@ else if ("Server".equals(configuration.getType())) setting.toLaunchOptions(profile.getGameDir(), !setting.isNotCheckJVM()), launcherVisibility == LauncherVisibility.CLOSE ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. - : new HMCLProcessListener(repository, selectedVersion, authInfo, gameVersion.isPresent()) + : new HMCLProcessListener(repository, selectedVersion, authInfo, launchingLatch, gameVersion.isPresent()) ); }).thenComposeAsync(launcher -> { // launcher is prev task's result if (scriptFile == null) { @@ -195,7 +195,6 @@ else if ("Server".equals(configuration.getType())) }); } }).thenRunAsync(Schedulers.defaultScheduler(), () -> { - launchingLatch = new CountDownLatch(1); launchingLatch.await(); }).withStage("launch.state.waiting_launching")) .withStagesHint(Lang.immutableListOf( @@ -451,11 +450,13 @@ class HMCLProcessListener implements ProcessListener { private LogWindow logWindow; private final boolean detectWindow; private final LinkedList> logs; - private final CountDownLatch latch = new CountDownLatch(1); + private final CountDownLatch logWindowLatch = new CountDownLatch(1); + private final CountDownLatch launchingLatch; - public HMCLProcessListener(HMCLGameRepository repository, String version, AuthInfo authInfo, boolean detectWindow) { + public HMCLProcessListener(HMCLGameRepository repository, String version, AuthInfo authInfo, CountDownLatch launchingLatch, boolean detectWindow) { this.repository = repository; this.version = version; + this.launchingLatch = launchingLatch; this.detectWindow = detectWindow; if (authInfo == null) @@ -484,7 +485,7 @@ public void setProcess(ManagedProcess process) { Platform.runLater(() -> { logWindow = new LogWindow(); logWindow.show(); - latch.countDown(); + logWindowLatch.countDown(); }); } @@ -504,9 +505,7 @@ private void finishLaunch() { // Never come to here. break; case KEEP: - Platform.runLater(() -> { - launchingLatch.countDown(); - }); + Platform.runLater(launchingLatch::countDown); break; case HIDE: launchingLatch.countDown(); @@ -541,7 +540,7 @@ public synchronized void onLog(String log, Log4jLevel level) { if (showLogs) { try { - latch.await(); + logWindowLatch.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; From 02cb2a3fb1fae0488c0b2bd1425effcfba865311 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 22 Apr 2020 23:52:51 +0800 Subject: [PATCH 0354/2639] add: accept authlib-injector artifact in current working directory --- .../main/java/org/jackhuang/hmcl/setting/Accounts.java | 8 +++++++- .../auth/authlibinjector/AuthlibInjectorDownloader.java | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) 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 4427fb687b..ac89e0f461 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -40,6 +40,7 @@ import org.jackhuang.hmcl.task.Schedulers; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -243,7 +244,12 @@ public static ObjectProperty selectedAccountProperty() { private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() { String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location"); if (authlibinjectorLocation == null) { - return new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider); + Path currentDirectory = Paths.get("."); + Path artifactsDirectory = AuthlibInjectorDownloader.isArtifactsDirectory(currentDirectory) + ? currentDirectory + : Metadata.HMCL_DIRECTORY; + + return new AuthlibInjectorDownloader(artifactsDirectory, DownloadProviders::getDownloadProvider); } else { LOG.info("Using specified authlib-injector: " + authlibinjectorLocation); return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java index 82953f6622..33fe053be8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java @@ -127,6 +127,10 @@ private Optional getLocalArtifact() { } } + public static boolean isArtifactsDirectory(Path artifactsDirectory) { + return Files.exists(artifactsDirectory.resolve("authlib-injector.jar")); + } + private static class AuthlibInjectorVersionInfo { @SerializedName("build_number") public int buildNumber; From 43de254a98a861de4b5083d8e38330a27506c72a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 08:02:55 +0800 Subject: [PATCH 0355/2639] fix: ConcurrentModificationException --- .../org/jackhuang/hmcl/download/VersionList.java | 14 +++++++------- .../hmcl/download/game/GameVersionList.java | 7 +------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index 4f23785668..f9d1c062b8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -100,12 +100,7 @@ public Task loadAsync(String gameVersion) { } protected Collection getVersionsImpl(String gameVersion) { - lock.readLock().lock(); - try { - return versions.get(gameVersion); - } finally { - lock.readLock().unlock(); - } + return versions.get(gameVersion); } /** @@ -115,7 +110,12 @@ protected Collection getVersionsImpl(String gameVersion) { * @return the collection of specific remote versions */ public final Collection getVersions(String gameVersion) { - return Collections.unmodifiableCollection(getVersionsImpl(gameVersion)); + lock.readLock().lock(); + try { + return Collections.unmodifiableCollection(new ArrayList<>(getVersionsImpl(gameVersion))); + } finally { + lock.readLock().unlock(); + } } /** diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java index be667e0b11..d64553633f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java @@ -45,12 +45,7 @@ public boolean hasType() { @Override protected Collection getVersionsImpl(String gameVersion) { - lock.readLock().lock(); - try { - return versions.values(); - } finally { - lock.readLock().unlock(); - } + return versions.values(); } @Override From 383de6cb2e6b11d061e9747480adbb08c01a152a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 08:12:19 +0800 Subject: [PATCH 0356/2639] fix: crash when renaming game version --- .../java/org/jackhuang/hmcl/ui/versions/Versions.java | 8 ++++++-- .../org/jackhuang/hmcl/game/DefaultGameRepository.java | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index 239f0857f2..e28998cde3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -60,8 +60,12 @@ public static void deleteVersion(Profile profile, String version) { } public static CompletableFuture renameVersion(Profile profile, String version) { - return Controllers.prompt(i18n("version.manage.rename.message"), (res, resolve, reject) -> { - if (profile.getRepository().renameVersion(version, res)) { + return Controllers.prompt(i18n("version.manage.rename.message"), (newName, resolve, reject) -> { + if (!OperatingSystem.isNameValid(newName)) { + reject.accept(i18n("install.new_game.malformed")); + return; + } + if (profile.getRepository().renameVersion(version, newName)) { profile.getRepository().refreshVersionsAsync().start(); resolve.run(); } else { 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 072a8ee872..730cb03473 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -38,8 +38,8 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -181,7 +181,7 @@ public boolean renameVersion(String from, String to) { fromVersion = fromVersion.setJar(null); FileUtils.writeText(toJson.toFile(), JsonUtils.GSON.toJson(fromVersion.setId(to))); return true; - } catch (IOException | JsonParseException | VersionNotFoundException e) { + } catch (IOException | JsonParseException | VersionNotFoundException | InvalidPathException e) { LOG.log(Level.WARNING, "Unable to rename version " + from + " to " + to, e); return false; } From eb9d12317651edd08aa3f7d2e9476872ad10f7d0 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 09:50:22 +0800 Subject: [PATCH 0357/2639] fix: IllegalArgumentException --- .../AuthlibInjectorServer.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java index 73b412cd39..6b01d7663c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java @@ -60,32 +60,36 @@ public class AuthlibInjectorServer implements Observable { private static final Gson GSON = new GsonBuilder().create(); public static AuthlibInjectorServer locateServer(String url) throws IOException { - url = parseInputUrl(url); - HttpURLConnection conn; - int redirectCount = 0; - for (;;) { - conn = (HttpURLConnection) new URL(url).openConnection(); - Optional ali = getApiLocationIndication(conn); - if (ali.isPresent()) { - conn.disconnect(); - url = ali.get(); - if (redirectCount >= MAX_REDIRECTS) { - throw new IOException("Exceeded maximum number of redirects (" + MAX_REDIRECTS + ")"); + try { + url = parseInputUrl(url); + HttpURLConnection conn; + int redirectCount = 0; + for (; ; ) { + conn = (HttpURLConnection) new URL(url).openConnection(); + Optional ali = getApiLocationIndication(conn); + if (ali.isPresent()) { + conn.disconnect(); + url = ali.get(); + if (redirectCount >= MAX_REDIRECTS) { + throw new IOException("Exceeded maximum number of redirects (" + MAX_REDIRECTS + ")"); + } + redirectCount++; + LOG.info("Redirect API root to: " + url); + } else { + break; } - redirectCount++; - LOG.info("Redirect API root to: " + url); - } else { - break; } - } - try { - AuthlibInjectorServer server = new AuthlibInjectorServer(url); - server.refreshMetadata(readFullyWithoutClosing(conn.getInputStream())); - return server; - } finally { - conn.disconnect(); + try { + AuthlibInjectorServer server = new AuthlibInjectorServer(url); + server.refreshMetadata(readFullyWithoutClosing(conn.getInputStream())); + return server; + } finally { + conn.disconnect(); + } + } catch (IllegalArgumentException e) { + throw new IOException(e); } } From a3b74e0c757f716b8305a4da5c0ad690a4e0e37a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 09:50:43 +0800 Subject: [PATCH 0358/2639] fix: RejectedExecutionException --- HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java | 3 ++- 1 file changed, 2 insertions(+), 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 e6f09d378f..69a144600e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -63,6 +63,7 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.RejectedExecutionException; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.util.Lang.mapOf; @@ -109,7 +110,7 @@ public void launch() { Controllers.dialog(launchingStepsPane); Schedulers.newThread().execute(this::launch0); }); - } catch (InterruptedException ignore) { + } catch (InterruptedException | RejectedExecutionException ignore) { } }); } From d574d8d78b53269be8479bd47e18bbfe4627de5b Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 11:13:03 +0800 Subject: [PATCH 0359/2639] fix: InvalidPathException when custom run directory is not valid --- .../jackhuang/hmcl/game/HMCLGameRepository.java | 14 ++++++++++---- .../org/jackhuang/hmcl/util/io/FileUtils.java | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 4 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 8f6c2c7434..b6789d7d5b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -62,10 +62,16 @@ public GameDirectoryType getGameDirectoryType(String id) { @Override public File getRunDirectory(String id) { switch (getGameDirectoryType(id)) { - case VERSION_FOLDER: return getVersionRoot(id); - case ROOT_FOLDER: return super.getRunDirectory(id); - case CUSTOM: return new File(getVersionSetting(id).getGameDir()); - default: throw new Error(); + case VERSION_FOLDER: + return getVersionRoot(id); + case ROOT_FOLDER: + return super.getRunDirectory(id); + case CUSTOM: + File dir = new File(getVersionSetting(id).getGameDir()); + if (!FileUtils.isValidPath(dir)) return getVersionRoot(id); + return dir; + default: + throw new Error(); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java index f58216f962..a76d3a1c03 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java @@ -390,4 +390,19 @@ public static List listFilesByExtension(File file, String extension) { result.add(it); return result; } + + /** + * Tests whether the file is convertible to [java.nio.file.Path] or not. + * + * @param file the file to be tested + * @return true if the file is convertible to Path. + */ + public static boolean isValidPath(File file) { + try { + file.toPath(); + return true; + } catch (InvalidPathException ignored) { + return false; + } + } } From 886ebe68856709ee7b14013a6017771c80125b71 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 11:26:40 +0800 Subject: [PATCH 0360/2639] alt: alignment --- .../java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 663fa2a237..651fb74d56 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -249,7 +249,8 @@ private Node createNavBar(Decorator skinnable, boolean titleBarTransparent, doub } if (titleNode != null) { titleLabel.prefWidthProperty().bind(Bindings.createDoubleBinding(() -> { - return leftPaneWidth - 20 - backNavButton.getWidth() - closeNavButton.getWidth(); + // 18 = 10 (horizontal padding of navLeft) + 8 (margin-left) + return leftPaneWidth - 18 - backNavButton.getWidth() - closeNavButton.getWidth(); }, backNavButton.widthProperty(), closeNavButton.widthProperty())); } titleLabel.setText(title); From 9bda50f66eacba6cca6680334eedad1014348ca0 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 12:10:25 +0800 Subject: [PATCH 0361/2639] alt: color of scrollbar in popup menu --- .../java/org/jackhuang/hmcl/ui/construct/PopupMenu.java | 3 ++- HMCL/src/main/resources/assets/css/root.css | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java index 2309c15c0d..a149cc9222 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PopupMenu.java @@ -38,6 +38,7 @@ public class PopupMenu extends Control { private final BooleanProperty alwaysShowingVBar = new SimpleBooleanProperty(); public PopupMenu() { + getStyleClass().add("popup-menu"); } public ObservableList getContent() { @@ -82,7 +83,7 @@ protected PopupMenuSkin() { .otherwise(ScrollPane.ScrollBarPolicy.AS_NEEDED)); VBox content = new VBox(); - content.getStyleClass().add("menu"); + content.getStyleClass().add("content"); Bindings.bindContent(content.getChildren(), PopupMenu.this.getContent()); scrollPane.setContent(content); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 5c1d9da7f1..0dc99cd848 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -106,7 +106,11 @@ -fx-padding: 8 16 8 16; } -.menu { +.popup-menu .scroll-bar .thumb { + -fx-fill: rgba(0, 0, 0, 0.5); +} + +.popup-menu .content { -fx-padding: 4 0 4 0; } From bc842437faa921401e69330e9e3e2a33466c08a6 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 23 Apr 2020 12:28:11 +0800 Subject: [PATCH 0362/2639] fix: breaking versions that inherit from a version being renamed --- .../jackhuang/hmcl/game/HMCLModpackInstallTask.java | 2 +- .../ui/download/UpdateInstallerWizardProvider.java | 2 +- .../jackhuang/hmcl/ui/versions/InstallerListPage.java | 4 ++-- .../jackhuang/hmcl/download/DefaultGameBuilder.java | 2 +- .../jackhuang/hmcl/download/game/GameInstallTask.java | 2 +- .../org/jackhuang/hmcl/game/DefaultGameRepository.java | 10 +++++++++- .../hmcl/mod/multimc/MultiMCModpackInstallTask.java | 2 +- 7 files changed, 16 insertions(+), 8 deletions(-) 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 3d7e2167b8..38e6217b5e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -104,7 +104,7 @@ public void execute() throws Exception { libraryTask = libraryTask.thenComposeAsync(version -> dependency.installLibraryAsync(modpack.getGameVersion(), version, mark.getLibraryId(), mark.getLibraryVersion())); } - dependencies.add(libraryTask.thenComposeAsync(repository::save)); + dependencies.add(libraryTask.thenComposeAsync(repository::saveAsync)); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java index d77c18466a..c019777a8f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java @@ -96,7 +96,7 @@ public Object finish(Map settings) { } } - return ret.thenComposeAsync(profile.getRepository()::save).thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHint(stages); + return ret.thenComposeAsync(profile.getRepository()::saveAsync).thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHint(stages); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index 336f3c9126..c2976bb737 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -76,7 +76,7 @@ public CompletableFuture loadVersion(Profile profile, String versionId) { }).thenAcceptAsync(analyzer -> { Function> removeAction = libraryId -> x -> { profile.getDependency().removeLibraryAsync(version, libraryId) - .thenComposeAsync(profile.getRepository()::save) + .thenComposeAsync(profile.getRepository()::saveAsync) .withComposeAsync(profile.getRepository().refreshVersionsAsync()) .withRunAsync(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId)) .start(); @@ -122,7 +122,7 @@ public void installOffline() { private void doInstallOffline(File file) { Task task = profile.getDependency().installLibraryAsync(version, file.toPath()) - .thenComposeAsync(profile.getRepository()::save) + .thenComposeAsync(profile.getRepository()::saveAsync) .thenComposeAsync(profile.getRepository().refreshVersionsAsync()); task.setName(i18n("install.installer.install_offline")); TaskExecutor executor = task.executor(new TaskListener() { 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 09c8bafedd..1f80d44b1f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -60,7 +60,7 @@ public Task buildAsync() { stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); } - return libraryTask.thenComposeAsync(dependencyManager.getGameRepository()::save).whenComplete(exception -> { + return libraryTask.thenComposeAsync(dependencyManager.getGameRepository()::saveAsync).whenComplete(exception -> { if (exception != null) dependencyManager.getGameRepository().removeVersionFromDisk(name); }).withStagesHint(stages); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java index 4a66319985..0806a2a30c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java @@ -77,7 +77,7 @@ public void execute() throws Exception { ).withStage("hmcl.install.assets").withRunAsync(() -> { // ignore failure }) - ).thenComposeAsync(gameRepository.save(version))); + ).thenComposeAsync(gameRepository.saveAsync(version))); } } 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 730cb03473..1824a688d8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -180,6 +180,14 @@ public boolean renameVersion(String from, String to) { if (fromVersion.getId().equals(fromVersion.getJar())) fromVersion = fromVersion.setJar(null); FileUtils.writeText(toJson.toFile(), JsonUtils.GSON.toJson(fromVersion.setId(to))); + + // fix inheritsFrom of versions that inherits from version [from]. + for (Version version : getVersions()) { + if (from.equals(version.getInheritsFrom())) { + File json = getVersionJson(version.getId()).getAbsoluteFile(); + FileUtils.writeText(json, JsonUtils.GSON.toJson(version.setInheritsFrom(to))); + } + } return true; } catch (IOException | JsonParseException | VersionNotFoundException | InvalidPathException e) { LOG.log(Level.WARNING, "Unable to rename version " + from + " to " + to, e); @@ -408,7 +416,7 @@ protected File reconstructAssets(String version, String assetId) throws IOExcept return assetsDir; } - public Task save(Version version) { + public Task saveAsync(Version version) { if (version.isResolvedPreservingPatches()) { return new VersionJsonSaveTask(this, MaintainTask.maintainPreservingPatches(this, version)); } else { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index ea8249d310..58f9e33256 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -180,7 +180,7 @@ public void execute() throws Exception { FileUtils.copyDirectory(jarmods, repository.getVersionRoot(name).toPath().resolve("jarmods")); } - dependencies.add(repository.save(version)); + dependencies.add(repository.saveAsync(version)); } @Override From c408cccd35bbe11e074912ec2571a397ae7b86da Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 24 Apr 2020 14:13:24 +0800 Subject: [PATCH 0363/2639] alt: buttons in game list now also available in version page --- .../hmcl/ui/versions/VersionPage.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index 80100cee53..839b08cdeb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -21,6 +21,7 @@ import com.jfoenix.controls.JFXListCell; import com.jfoenix.controls.JFXListView; import com.jfoenix.controls.JFXPopup; +import com.jfoenix.effects.JFXDepthManager; import javafx.application.Platform; import javafx.beans.property.*; import javafx.geometry.Pos; @@ -36,6 +37,7 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.ToolbarListPageSkin; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionPane; import org.jackhuang.hmcl.ui.construct.*; @@ -266,8 +268,27 @@ public ListCell call(ListView param) { // the root page, with the sidebar in left, navigator in center. BorderPane root = new BorderPane(); - FXUtils.setLimitWidth(control.listView, 200); - root.setLeft(control.listView); + + { + BorderPane left = new BorderPane(); + FXUtils.setLimitWidth(left, 200); + left.setCenter(control.listView); + root.setLeft(left); + + JFXButton btnAddGame = ToolbarListPageSkin.createToolbarButton(null, SVG::plus, GameList::addNewGame); + FXUtils.installFastTooltip(btnAddGame, new Tooltip(i18n("install.new_game"))); + + JFXButton btnImportModpack = ToolbarListPageSkin.createToolbarButton(null, SVG::importIcon, GameList::importModpack); + FXUtils.installFastTooltip(btnImportModpack, new Tooltip(i18n("install.modpack"))); + + JFXButton btnRefresh = ToolbarListPageSkin.createToolbarButton(null, SVG::refresh, GameList::refreshList); + FXUtils.installFastTooltip(btnRefresh, new Tooltip(i18n("button.refresh"))); + + HBox toolbar = new HBox(); + toolbar.setPickOnBounds(false); + toolbar.getChildren().setAll(btnAddGame, btnImportModpack, btnRefresh); + left.setTop(toolbar); + } TabHeader tabPane = new TabHeader(); tabPane.setPickOnBounds(false); From b933938f1bee072fb87892d6a90f7e8c559e2ef6 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 24 Apr 2020 14:13:46 +0800 Subject: [PATCH 0364/2639] alt: show better prompt in game launching. --- .../jackhuang/hmcl/game/LauncherHelper.java | 21 +++++++++++++++---- .../UpdateInstallerWizardProvider.java | 9 ++++---- .../jackhuang/hmcl/ui/versions/GameList.java | 14 ++++++------- 3 files changed, 28 insertions(+), 16 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 69a144600e..fa78440e89 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -37,10 +37,7 @@ import org.jackhuang.hmcl.setting.LauncherVisibility; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; -import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.task.TaskExecutor; -import org.jackhuang.hmcl.task.TaskListener; +import org.jackhuang.hmcl.task.*; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; import org.jackhuang.hmcl.ui.LogWindow; @@ -49,6 +46,7 @@ import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; +import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jackhuang.hmcl.util.platform.CommandBuilder; import org.jackhuang.hmcl.util.platform.JavaVersion; @@ -59,6 +57,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.net.SocketTimeoutException; import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; @@ -241,6 +240,20 @@ public void onStop(boolean success, TaskExecutor executor) { } else { message += StringUtils.getStackTrace(ex.getCause()); } + } else if (ex instanceof DownloadException) { + URL url = ((DownloadException) ex).getUrl(); + if (ex.getCause() instanceof SocketTimeoutException) { + message = i18n("install.failed.downloading.timeout", url); + } else if (ex.getCause() instanceof ResponseCodeException) { + ResponseCodeException responseCodeException = (ResponseCodeException) ex.getCause(); + if (I18n.hasKey("download.code." + responseCodeException.getResponseCode())) { + message = i18n("download.code." + responseCodeException.getResponseCode(), url); + } else { + message = i18n("install.failed.downloading.detail", url) + "\n" + StringUtils.getStackTrace(ex.getCause()); + } + } else { + message = i18n("install.failed.downloading.detail", url) + "\n" + StringUtils.getStackTrace(ex.getCause()); + } } else if (ex instanceof GameAssetIndexDownloadTask.GameAssetIndexMalformedException) { message = i18n("assets.index.malformed"); } else if (ex instanceof AuthlibInjectorDownloadException) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java index c019777a8f..8ec6b5da80 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java @@ -147,17 +147,18 @@ public static void alertFailureMessage(Exception exception, Runnable next) { } Controllers.dialog(message, i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); } else if (exception instanceof DownloadException) { + URL url = ((DownloadException) exception).getUrl(); if (exception.getCause() instanceof SocketTimeoutException) { - Controllers.dialog(i18n("install.failed.downloading.timeout", ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + Controllers.dialog(i18n("install.failed.downloading.timeout", url), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); } else if (exception.getCause() instanceof ResponseCodeException) { ResponseCodeException responseCodeException = (ResponseCodeException) exception.getCause(); if (I18n.hasKey("download.code." + responseCodeException.getResponseCode())) { - Controllers.dialog(i18n("download.code." + responseCodeException.getResponseCode(), ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + Controllers.dialog(i18n("download.code." + responseCodeException.getResponseCode(), url), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); } else { - Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + Controllers.dialog(i18n("install.failed.downloading.detail", url) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); } } else { - Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + Controllers.dialog(i18n("install.failed.downloading.detail", url) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); } } else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException || exception instanceof FabricInstallTask.UnsupportedFabricInstallationException) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java index 226d51367b..4064b85cf5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.versions; -import javafx.application.Platform; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.scene.Node; @@ -30,7 +29,6 @@ import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; import org.jackhuang.hmcl.ui.*; -import org.jackhuang.hmcl.ui.construct.Navigator; import org.jackhuang.hmcl.ui.decorator.DecoratorPage; import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider; import org.jackhuang.hmcl.ui.download.VanillaInstallWizardProvider; @@ -98,21 +96,21 @@ protected GameListSkin createDefaultSkin() { return new GameListSkin(); } - void addNewGame() { + public static void addNewGame() { Profile profile = Profiles.getSelectedProfile(); if (profile.getRepository().isLoaded()) { Controllers.getDecorator().startWizard(new VanillaInstallWizardProvider(profile), i18n("install.new_game")); } } - void importModpack() { + public static void importModpack() { Profile profile = Profiles.getSelectedProfile(); if (profile.getRepository().isLoaded()) { Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(profile), i18n("install.modpack")); } } - public void refresh() { + public static void refreshList() { Profiles.getSelectedProfile().getRepository().refreshVersionsAsync().start(); } @@ -131,9 +129,9 @@ public GameListSkin() { super(GameList.this); HBox hbox = new HBox( - createToolbarButton(i18n("install.new_game"), SVG::plus, GameList.this::addNewGame), - createToolbarButton(i18n("install.modpack"), SVG::importIcon, GameList.this::importModpack), - createToolbarButton(i18n("button.refresh"), SVG::refresh, GameList.this::refresh), + createToolbarButton(i18n("install.new_game"), SVG::plus, GameList::addNewGame), + createToolbarButton(i18n("install.modpack"), SVG::importIcon, GameList::importModpack), + createToolbarButton(i18n("button.refresh"), SVG::refresh, GameList::refreshList), createToolbarButton(i18n("settings.type.global.manage"), SVG::gear, GameList.this::modifyGlobalGameSettings) ); hbox.setPickOnBounds(false); From 810ea9ace961fc1e09bc61841b6170929b3422e5 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 24 Apr 2020 23:12:58 +0800 Subject: [PATCH 0365/2639] add: remember window size --- .../java/org/jackhuang/hmcl/Launcher.java | 6 ++++ .../org/jackhuang/hmcl/setting/Config.java | 30 +++++++++++++++++++ .../org/jackhuang/hmcl/ui/Controllers.java | 13 ++++++++ 3 files changed, 49 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 8762f610d0..1158b2e1b0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -74,6 +74,12 @@ public void start(Stage primaryStage) { } } + @Override + public void stop() throws Exception { + super.stop(); + Controllers.onApplicationStop(); + } + public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); AsyncTaskExecutor.setUncaughtExceptionHandler(new CrashReporter(false)); 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 c41786138f..aa18ee3f76 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -110,6 +110,12 @@ public static Config fromJson(String json) throws JsonParseException { @SerializedName("proxyPassword") private StringProperty proxyPass = new SimpleStringProperty(); + @SerializedName("width") + private DoubleProperty width = new SimpleDoubleProperty(); + + @SerializedName("height") + private DoubleProperty height = new SimpleDoubleProperty(); + @SerializedName("theme") private ObjectProperty theme = new SimpleObjectProperty<>(Theme.BLUE); @@ -329,6 +335,30 @@ public StringProperty proxyPassProperty() { return proxyPass; } + public double getWidth() { + return width.get(); + } + + public DoubleProperty widthProperty() { + return width; + } + + public void setWidth(double width) { + this.width.set(width); + } + + public double getHeight() { + return height.get(); + } + + public DoubleProperty heightProperty() { + return height; + } + + public void setHeight(double height) { + this.height.set(height); + } + public Theme getTheme() { return theme.get(); } 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 eda9e3bbb3..92c92ef2e2 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,8 @@ */ package org.jackhuang.hmcl.ui; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.layout.Region; @@ -50,6 +52,8 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class Controllers { + private static DoubleProperty stageWidth = new SimpleDoubleProperty(); + private static DoubleProperty stageHeight = new SimpleDoubleProperty(); private static Scene scene; private static Stage stage; @@ -92,12 +96,21 @@ public static DecoratorController getDecorator() { return decorator; } + public static void onApplicationStop() { + config().setHeight(stageHeight.get()); + config().setWidth(stageWidth.get()); + } public static void initialize(Stage stage) { Logging.LOG.info("Start initializing application"); Controllers.stage = stage; + stage.setHeight(config().getHeight()); + stageHeight.bind(stage.heightProperty()); + stage.setWidth(config().getWidth()); + stageWidth.bind(stage.widthProperty()); + stage.setOnCloseRequest(e -> Launcher.stopApplication()); decorator = new DecoratorController(stage, getRootPage()); From fec5c9a5ce577076bda261b675c0b48f21cebdcf Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 25 Apr 2020 01:14:31 +0800 Subject: [PATCH 0366/2639] fix: AccessDeniedException when updating server modpack --- HMCL/src/main/java/org/jackhuang/hmcl/Main.java | 5 ++++- .../hmcl/ui/account/AccountListItemSkin.java | 1 - .../hmcl/ui/construct/FloatScrollBarSkin.java | 4 ---- .../hmcl/ui/download/RemoteModpackPage.java | 9 --------- .../hmcl/ui/profile/ProfileListItemSkin.java | 1 - .../hmcl/ui/versions/GameListItemSkin.java | 1 - .../hmcl/ui/versions/ModListPageSkin.java | 1 - .../jackhuang/hmcl/ui/versions/VersionPage.java | 1 - .../hmcl/ui/versions/WorldListItemSkin.java | 1 - .../hmcl/download/LibraryAnalyzer.java | 1 - .../hmcl/download/fabric/FabricVersionList.java | 1 - .../hmcl/download/forge/ForgeInstallTask.java | 4 ++-- .../download/forge/ForgeNewInstallTask.java | 1 - .../download/optifine/OptiFineInstallTask.java | 2 -- .../java/org/jackhuang/hmcl/event/EventBus.java | 1 - .../org/jackhuang/hmcl/event/EventManager.java | 1 - .../jackhuang/hmcl/mod/FabricModMetadata.java | 17 +++++++++++------ .../java/org/jackhuang/hmcl/mod/ModAdviser.java | 1 - .../jackhuang/hmcl/mod/ModpackInstallTask.java | 2 +- .../java/org/jackhuang/hmcl/mod/PackMcMeta.java | 6 +++--- .../multimc/MultiMCInstanceConfiguration.java | 6 ++++-- .../hmcl/mod/multimc/MultiMCManifest.java | 6 +++--- .../mod/multimc/MultiMCModpackInstallTask.java | 8 ++------ .../mod/server/ServerModpackCompletionTask.java | 2 +- .../server/ServerModpackRemoteInstallTask.java | 3 --- .../hmcl/util/platform/OperatingSystem.java | 2 -- 26 files changed, 31 insertions(+), 57 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index 8928cb6205..7c2a6a04ca 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -128,7 +128,10 @@ static void fixLetsEncrypt() { try { KeyStore defaultKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); Path ksPath = Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts"); - defaultKeyStore.load(Files.newInputStream(ksPath), "changeit".toCharArray()); + + try (InputStream ksStream = Files.newInputStream(ksPath)) { + defaultKeyStore.load(ksStream, "changeit".toCharArray()); + } KeyStore letsEncryptKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); InputStream letsEncryptFile = Main.class.getResourceAsStream("/assets/lekeystore.jks"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 6b04d251fc..6da83205f5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -20,7 +20,6 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; -import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.SkinBase; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java index 1dfeee6e7d..821ed68010 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FloatScrollBarSkin.java @@ -121,10 +121,6 @@ private double thumbLength() { return getSkinnable().getOrientation() == Orientation.VERTICAL ? thumb.getHeight() : thumb.getWidth(); } - private double boundedSize(double min, double value, double max) { - return Math.min(Math.max(value, min), Math.max(min, max)); - } - private void setup() { track.widthProperty().unbind(); track.heightProperty().unbind(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index cd1df04b6b..e84ae018e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -24,13 +24,8 @@ import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; -import javafx.stage.FileChooser; -import org.jackhuang.hmcl.game.ModpackHelper; -import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.mod.server.ServerModpackManifest; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.task.Schedulers; -import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.WebStage; @@ -40,10 +35,6 @@ import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.gson.JsonUtils; -import org.jackhuang.hmcl.util.io.CompressingUtils; - -import java.io.File; import java.io.IOException; import java.util.Map; import java.util.Optional; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java index 48e61af606..60b2d34c2b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java @@ -20,7 +20,6 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; -import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index 873bdb5906..f096499eb1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -21,7 +21,6 @@ import com.jfoenix.controls.JFXPopup; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; -import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Cursor; import javafx.scene.control.SkinBase; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index e46607deaf..d5cbb73c05 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -23,7 +23,6 @@ import com.jfoenix.effects.JFXDepthManager; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; -import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.SelectionMode; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index 839b08cdeb..6444236b7a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -21,7 +21,6 @@ import com.jfoenix.controls.JFXListCell; import com.jfoenix.controls.JFXListView; import com.jfoenix.controls.JFXPopup; -import com.jfoenix.effects.JFXDepthManager; import javafx.application.Platform; import javafx.beans.property.*; import javafx.geometry.Pos; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java index 1f0b8cf679..7b740ac98f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java @@ -20,7 +20,6 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXPopup; import com.jfoenix.effects.JFXDepthManager; -import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index acdb8b2356..2486226730 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.function.BiConsumer; import java.util.regex.Pattern; import java.util.stream.Collectors; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java index cdac8f2bfd..10bd933675 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.Nullable; -import javax.xml.stream.XMLStreamException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; 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 5dc7ae8951..3e8fd366c0 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 @@ -134,7 +134,7 @@ public static boolean detectForgeInstallerType(DependencyManager dependencyManag if (!gameVersion.isPresent()) throw new IOException(); try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { String installProfileText = FileUtils.readText(fs.getPath("install_profile.json")); - Map installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); + Map installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); if (installProfile.containsKey("spec")) { ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class); if (!gameVersion.get().equals(profile.getMinecraft())) @@ -167,7 +167,7 @@ public static Task install(DefaultDependencyManager dependencyManager, if (!gameVersion.isPresent()) throw new IOException(); try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { String installProfileText = FileUtils.readText(fs.getPath("install_profile.json")); - Map installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); + Map installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); if (installProfile.containsKey("spec")) { ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class); if (!gameVersion.get().equals(profile.getMinecraft())) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java index d5f33aab29..2f53c5774a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.game.GameLibrariesTask; -import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.Artifact; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.Library; 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 430b057a59..43751f954e 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,8 +38,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.stream.Collectors; - import static org.jackhuang.hmcl.util.Lang.getOrDefault; /** 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 5e3fe02c2b..b9f7639208 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventBus.java @@ -19,7 +19,6 @@ import org.jackhuang.hmcl.util.Logging; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; /** diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventManager.java index 1ea09987c1..507160c8dc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/event/EventManager.java @@ -21,7 +21,6 @@ import java.lang.ref.WeakReference; import java.util.EnumMap; -import java.util.HashSet; import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.Consumer; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/FabricModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/FabricModMetadata.java index e2060014ca..316a99196a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/FabricModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/FabricModMetadata.java @@ -17,12 +17,19 @@ */ package org.jackhuang.hmcl.mod; -import com.google.gson.*; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import com.google.gson.annotations.JsonAdapter; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; -import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; @@ -30,9 +37,7 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Immutable @@ -60,7 +65,7 @@ public static ModInfo fromFile(ModManager modManager, File modFile) throws IOExc Path mcmod = fs.getPath("fabric.mod.json"); if (Files.notExists(mcmod)) throw new IOException("File " + modFile + " is not a Fabric mod."); - FabricModMetadata metadata = JsonUtils.fromNonNullJson(IOUtils.readFullyAsString(Files.newInputStream(mcmod)), FabricModMetadata.class); + FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class); String authors = metadata.authors == null ? "" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(", ")); return new ModInfo(modManager, modFile, metadata.name, metadata.description, authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : ""); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java index 8f623bd8fe..944a9fd0a7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java @@ -20,7 +20,6 @@ import org.jackhuang.hmcl.util.Lang; import java.util.List; -import java.util.regex.Pattern; /** * @author huangyuhui diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java index d7f7f3b29e..bab40ed900 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackInstallTask.java @@ -91,7 +91,7 @@ public void execute() throws Exception { } else { // If both old and new modpacks have this entry, and user has modified this file, // we will not replace it since this modified file is what user expects. - String fileHash = encodeHex(digest("SHA-1", Files.newInputStream(destPath))); + String fileHash = encodeHex(digest("SHA-1", destPath)); String oldHash = files.get(entryPath).getHash(); return Objects.equals(oldHash, fileHash); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/PackMcMeta.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/PackMcMeta.java index 858bee49a5..f0be8149d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/PackMcMeta.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/PackMcMeta.java @@ -17,13 +17,13 @@ */ package org.jackhuang.hmcl.mod; -import com.google.gson.*; +import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.io.CompressingUtils; -import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; @@ -85,7 +85,7 @@ public static ModInfo fromFile(ModManager modManager, File modFile) throws IOExc Path mcmod = fs.getPath("pack.mcmeta"); if (Files.notExists(mcmod)) throw new IOException("File " + modFile + " is not a resource pack."); - PackMcMeta metadata = JsonUtils.fromNonNullJson(IOUtils.readFullyAsString(Files.newInputStream(mcmod)), PackMcMeta.class); + PackMcMeta metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), PackMcMeta.class); return new ModInfo(modManager, modFile, metadata.pack.description, "", "", "", "", ""); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java index 0165fcbb20..124a5a3945 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java @@ -352,8 +352,10 @@ public static Modpack readMultiMCModpackManifest(Path modpackFile, Charset encod Path instancePath = root.resolve("instance.cfg"); if (Files.notExists(instancePath)) throw new IOException("`instance.cfg` not found, " + modpackFile + " is not a valid MultiMC modpack."); - MultiMCInstanceConfiguration cfg = new MultiMCInstanceConfiguration(name, Files.newInputStream(instancePath), manifest); - return new Modpack(cfg.getName(), "", "", cfg.getGameVersion(), cfg.getNotes(), encoding, cfg); + try (InputStream instanceStream = Files.newInputStream(instancePath)) { + MultiMCInstanceConfiguration cfg = new MultiMCInstanceConfiguration(name, instanceStream, manifest); + return new Modpack(cfg.getName(), "", "", cfg.getGameVersion(), cfg.getNotes(), encoding, cfg); + } } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCManifest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCManifest.java index 39fc300ac7..d4bd7241a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCManifest.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCManifest.java @@ -20,12 +20,12 @@ import com.google.gson.annotations.SerializedName; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.JsonUtils; -import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; +import java.util.*; @Immutable public final class MultiMCManifest { @@ -60,7 +60,7 @@ public static MultiMCManifest readMultiMCModpackManifest(Path root) throws IOExc Path mmcPack = root.resolve("mmc-pack.json"); if (Files.notExists(mmcPack)) return null; - String json = IOUtils.readFullyAsString(Files.newInputStream(mmcPack)); + String json = FileUtils.readText(mmcPack); MultiMCManifest manifest = JsonUtils.fromNonNullJson(json, MultiMCManifest.class); if (manifest.getComponents() == null) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 58f9e33256..4a08b2fe37 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -32,7 +32,6 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.IOUtils; import java.io.File; import java.io.IOException; @@ -40,10 +39,7 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -156,7 +152,7 @@ public void execute() throws Exception { for (Path patchJson : directoryStream) { if (patchJson.toString().endsWith(".json")) { // If json is malformed, we should stop installing this modpack instead of skipping it. - MultiMCInstancePatch multiMCPatch = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(Files.newInputStream(patchJson)), MultiMCInstancePatch.class); + MultiMCInstancePatch multiMCPatch = JsonUtils.GSON.fromJson(FileUtils.readText(patchJson), MultiMCInstancePatch.class); List arguments = new ArrayList<>(); for (String arg : multiMCPatch.getTweakers()) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java index 5c1eca6c28..b4d45f9824 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java @@ -128,7 +128,7 @@ public void execute() throws Exception { download = true; } else { // If user modified this entry file, we will not replace this file since this modified file is that user expects. - String fileHash = encodeHex(digest("SHA-1", Files.newInputStream(actualPath))); + String fileHash = encodeHex(digest("SHA-1", actualPath)); String oldHash = files.get(file.getPath()).getHash(); download = !Objects.equals(oldHash, file.getHash()) && Objects.equals(oldHash, fileHash); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java index 152c267626..547118643e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java @@ -22,10 +22,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; -import org.jackhuang.hmcl.mod.MinecraftInstanceTask; -import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.mod.ModpackConfiguration; -import org.jackhuang.hmcl.mod.ModpackInstallTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java index 252b58b7b2..0f9fa004a9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java @@ -21,8 +21,6 @@ import javax.management.MBeanServer; import javax.management.ObjectName; -import org.jackhuang.hmcl.util.Lang; - import java.io.File; import java.lang.management.ManagementFactory; import java.nio.charset.Charset; From 4bac9380d1efe1162adba223186adc24589e27d1 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 25 Apr 2020 16:46:53 +0800 Subject: [PATCH 0367/2639] fix: game crash when Forge, OptiFine are both installed. --- .../org/jackhuang/hmcl/download/MaintainTask.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 aea850d912..7d91f48c3a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -106,6 +106,7 @@ private static Version maintainGameWithLaunchWrapper(Version version, boolean re // If forge or LiteLoader installed, OptiFine Forge Tweaker is needed. builder.replaceTweakClass("optifine", "optifine.OptiFineForgeTweaker", !reorderTweakClass); } + } } else { builder.removeTweakClass("optifine"); @@ -123,7 +124,7 @@ private static Version maintainOptiFineLibrary(GameRepository repository, Versio if (libraryAnalyzer.has(LITELOADER) || libraryAnalyzer.has(FORGE)) { // If forge or LiteLoader installed, OptiFine Forge Tweaker is needed. // And we should load the installer jar instead of patch jar. - if (repository != null) + if (repository != null) { for (int i = 0; i < version.getLibraries().size(); ++i) { Library library = libraries.get(i); if (library.is("optifine", "OptiFine")) { @@ -137,7 +138,15 @@ private static Version maintainOptiFineLibrary(GameRepository repository, Versio libraries.add(newLibrary); } } + + if (library.is("optifine", "launchwrapper-of")) { + // With MinecraftForge installed, the custom launchwrapper installed by OptiFine will conflicts + // with the one installed by MinecraftForge or LiteLoader or ModLoader. + // Simply removing it works. + libraries.set(i, null); + } } + } } } From cf1b91ec55c01dd27c4196c4ed488cb607d5b478 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 25 Apr 2020 19:45:28 +0800 Subject: [PATCH 0368/2639] alt: change selected version in VersionPage --- .../main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index 6444236b7a..357dbb4b21 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -119,6 +119,8 @@ private void loadVersions(Profile profile) { public void setVersion(String version, Profile profile) { this.version = version; this.profile = profile; + + profile.setSelectedVersion(version); } public void loadVersion(String version, Profile profile) { From 63e2fdf56dc95a005cec61504cbc908affad5040 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 25 Apr 2020 19:55:42 +0800 Subject: [PATCH 0369/2639] alt: show authlib injector server name in main screen. --- .../ui/account/AccountAdvancedListItem.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountAdvancedListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountAdvancedListItem.java index a6491f4dc0..b39bba5c2c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountAdvancedListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountAdvancedListItem.java @@ -18,12 +18,12 @@ package org.jackhuang.hmcl.ui.account; import javafx.beans.binding.Bindings; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.*; import javafx.collections.ObservableList; import javafx.scene.control.Tooltip; import org.jackhuang.hmcl.auth.Account; -import org.jackhuang.hmcl.auth.offline.OfflineAccount; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.TexturesLoader; import org.jackhuang.hmcl.setting.Accounts; @@ -54,7 +54,7 @@ protected void invalidated() { titleProperty().bind(Bindings.createStringBinding(account::getCharacter, account)); setSubtitle(accountSubtitle(account)); imageProperty().bind(TexturesLoader.fxAvatarBinding(account, 32)); - tooltip.setText(account.getCharacter() + " " + accountSubtitle(account)); + tooltip.setText(account.getCharacter() + " " + accountTooltip(account)); } } }; @@ -83,11 +83,22 @@ public ObjectProperty accountProperty() { } private static String accountSubtitle(Account account) { - if (account instanceof OfflineAccount) - return i18n("account.methods.offline"); - else if (account instanceof YggdrasilAccount) + String loginTypeName = Accounts.getLocalizedLoginTypeName(Accounts.getAccountFactory(account)); + if (account instanceof AuthlibInjectorAccount) { + return ((AuthlibInjectorAccount) account).getServer().getName(); + } else { + return loginTypeName; + } + } + + private static String accountTooltip(Account account) { + if (account instanceof AuthlibInjectorAccount) { + AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer(); + return account.getUsername() + ", " + i18n("account.injector.server") + ": " + server.getName(); + } else if (account instanceof YggdrasilAccount) { return account.getUsername(); - else + } else { return ""; + } } } From 1bba1b427c2d07b44289b78df93516d7aefc0265 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 20:17:13 +0800 Subject: [PATCH 0370/2639] fix: support downloading files from urls whose protocols are not http. --- .../download/fabric/FabricInstallTask.java | 4 +- .../hmcl/download/forge/ForgeInstallTask.java | 6 +- .../download/game/GameAssetDownloadTask.java | 10 +- .../game/GameAssetIndexDownloadTask.java | 6 +- .../hmcl/download/game/GameDownloadTask.java | 6 +- .../download/game/LibraryDownloadTask.java | 12 +- .../optifine/OptiFineInstallTask.java | 9 +- .../hmcl/mod/curse/CurseCompletionTask.java | 7 +- .../org/jackhuang/hmcl/task/FetchTask.java | 228 ++++++++++++++ .../jackhuang/hmcl/task/FileDownloadTask.java | 281 +++++------------- .../java/org/jackhuang/hmcl/task/GetTask.java | 95 ++---- .../java/org/jackhuang/hmcl/task/Task.java | 2 +- .../jackhuang/hmcl/util/io/NetworkUtils.java | 16 +- 13 files changed, 362 insertions(+), 320 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java index 699ff0155f..e577896a59 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java @@ -49,8 +49,8 @@ public FabricInstallTask(DefaultDependencyManager dependencyManager, Version ver this.version = version; this.remote = remoteVersion; - launchMetaTask = new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())) - .setCacheRepository(dependencyManager.getCacheRepository()); + launchMetaTask = new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())); + launchMetaTask.setCacheRepository(dependencyManager.getCacheRepository()); } @Override 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 3e8fd366c0..a558b65cca 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 @@ -72,9 +72,9 @@ public void preExecute() throws Exception { dependent = new FileDownloadTask( dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), - installer.toFile(), null) - .setCacheRepository(dependencyManager.getCacheRepository()) - .setCaching(true); + installer.toFile(), null); + dependent.setCacheRepository(dependencyManager.getCacheRepository()); + dependent.setCaching(true); dependent.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); } 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 f6b32d62f2..775f0fa93f 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 @@ -113,11 +113,11 @@ public void execute() throws Exception { FileDownloadTask task = new FileDownloadTask(urls, file, new FileDownloadTask.IntegrityCheck("SHA-1", assetObject.getHash())); task.setName(assetObject.getHash()); - dependencies.add(task - .setCacheRepository(dependencyManager.getCacheRepository()) - .setCaching(true) - .setCandidate(dependencyManager.getCacheRepository().getCommonDirectory() - .resolve("assets").resolve("objects").resolve(assetObject.getLocation())).withCounter()); + task.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory() + .resolve("assets").resolve("objects").resolve(assetObject.getLocation())); + task.setCacheRepository(dependencyManager.getCacheRepository()); + task.setCaching(true); + dependencies.add(task.withCounter()); } else { dependencyManager.getCacheRepository().tryCacheFile(file.toPath(), CacheRepository.SHA1, assetObject.getHash()); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index 3f56f2b5c4..a3731b87c6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -63,10 +63,12 @@ public void execute() { // We should not check the hash code of asset index file since this file is not consistent // And Mojang will modify this file anytime. So assetIndex.hash might be outdated. - dependencies.add(new FileDownloadTask( + FileDownloadTask task = new FileDownloadTask( dependencyManager.getDownloadProvider().injectURLWithCandidates(assetIndexInfo.getUrl()), assetIndexFile - ).setCacheRepository(dependencyManager.getCacheRepository())); + ); + task.setCacheRepository(dependencyManager.getCacheRepository()); + dependencies.add(task); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index 0b906dc54c..5844bde9a2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -59,9 +59,9 @@ public void execute() { FileDownloadTask task = new FileDownloadTask( dependencyManager.getDownloadProvider().injectURLWithCandidates(version.getDownloadInfo().getUrl()), jar, - IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1())) - .setCaching(true) - .setCacheRepository(dependencyManager.getCacheRepository()); + IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1())); + task.setCaching(true); + task.setCacheRepository(dependencyManager.getCacheRepository()); if (gameVersion != null) task.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory().resolve("jars").resolve(gameVersion + ".jar")); 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 f50644948a..8447e9b9c6 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 @@ -129,16 +129,16 @@ public void preExecute() throws Exception { URL packXz = NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(url) + ".pack.xz"); if (NetworkUtils.urlExists(packXz)) { List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz"); - task = new FileDownloadTask(urls, xzFile, null) - .setCacheRepository(cacheRepository) - .setCaching(true); + task = new FileDownloadTask(urls, xzFile, null); + task.setCacheRepository(cacheRepository); + task.setCaching(true); xz = true; } else { List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url); task = new FileDownloadTask(urls, jar, - library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null) - .setCacheRepository(cacheRepository) - .setCaching(true); + library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null); + task.setCacheRepository(cacheRepository); + task.setCaching(true); task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); xz = false; } 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 43751f954e..8764ed495d 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 @@ -92,11 +92,12 @@ public void preExecute() throws Exception { dest = Files.createTempFile("optifine-installer", ".jar"); if (installer == null) { - dependents.add(new FileDownloadTask( + FileDownloadTask task = new FileDownloadTask( dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), - dest.toFile(), null) - .setCacheRepository(dependencyManager.getCacheRepository()) - .setCaching(true)); + dest.toFile(), null); + task.setCacheRepository(dependencyManager.getCacheRepository()); + task.setCaching(true); + dependents.add(task); } else { FileUtils.copyFile(installer, dest); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java index 582556dff1..ac62aa2d8d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java @@ -149,9 +149,10 @@ public void execute() throws Exception { for (CurseManifestFile file : newManifest.getFiles()) if (StringUtils.isNotBlank(file.getFileName())) { if (!modManager.hasSimpleMod(file.getFileName())) { - dependencies.add(new FileDownloadTask(file.getUrl(), modManager.getSimpleModPath(file.getFileName()).toFile()) - .setCacheRepository(dependency.getCacheRepository()) - .setCaching(true).withCounter()); + FileDownloadTask task = new FileDownloadTask(file.getUrl(), modManager.getSimpleModPath(file.getFileName()).toFile()); + task.setCacheRepository(dependency.getCacheRepository()); + task.setCaching(true); + dependencies.add(task.withCounter()); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java new file mode 100644 index 0000000000..3f49b6c065 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java @@ -0,0 +1,228 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.task; + +import org.jackhuang.hmcl.event.Event; +import org.jackhuang.hmcl.event.EventBus; +import org.jackhuang.hmcl.util.CacheRepository; +import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.ToStringBuilder; +import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jackhuang.hmcl.util.io.ResponseCodeException; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +public abstract class FetchTask extends Task { + protected final List urls; + protected final int retry; + protected boolean caching; + protected CacheRepository repository = CacheRepository.getInstance(); + + public FetchTask(List urls, int retry) { + if (urls == null || urls.isEmpty()) + throw new IllegalArgumentException("At least one URL is required"); + + this.urls = new ArrayList<>(urls); + this.retry = retry; + + setExecutor(Schedulers.io()); + } + + public void setCaching(boolean caching) { + this.caching = caching; + } + + public void setCacheRepository(CacheRepository repository) { + this.repository = repository; + } + + protected void beforeDownload(URL url) throws IOException {} + + protected abstract void useCachedResult(Path cachedFile) throws IOException; + + protected abstract EnumCheckETag shouldCheckETag(); + + protected abstract Context getContext(URLConnection conn, boolean checkETag) throws IOException; + + @Override + public void execute() throws Exception { + Exception exception = null; + URL failedURL = null; + boolean checkETag; + switch (shouldCheckETag()) { + case CHECK_E_TAG: checkETag = true; break; + case NOT_CHECK_E_TAG: checkETag = false; break; + default: return; + } + + int repeat = 0; + download: for (URL url : urls) { + for (int retryTime = 0; retryTime < retry; retryTime++) { + if (isCancelled()) { + break download; + } + + try { + beforeDownload(url); + + updateProgress(0); + + URLConnection conn = NetworkUtils.createConnection(url); + if (checkETag) repository.injectConnection(conn); + + if (conn instanceof HttpURLConnection) { + conn = NetworkUtils.resolveConnection((HttpURLConnection) conn); + int responseCode = ((HttpURLConnection) conn).getResponseCode(); + + if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { + // Handle cache + try { + Path cache = repository.getCachedRemoteFile(conn); + useCachedResult(cache); + return; + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to use cached file, redownload " + url, e); + repository.removeRemoteEntry(conn); + // Now we must reconnect the server since 304 may result in empty content, + // if we want to redownload the file, we must reconnect the server without etag settings. + retryTime--; + continue; + } + } else if (responseCode / 100 == 4) { + break; // we will not try this URL again + } else if (responseCode / 100 != 2) { + throw new ResponseCodeException(url, responseCode); + } + } + + long contentLength = conn.getContentLength(); + try (Context context = getContext(conn, checkETag); InputStream stream = conn.getInputStream()) { + int lastDownloaded = 0, downloaded = 0; + byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; + while (true) { + if (isCancelled()) break; + + int len = stream.read(buffer); + if (len == -1) break; + + context.write(buffer, 0, len); + + downloaded += len; + + if (contentLength >= 0) { + // Update progress information per second + updateProgress(downloaded, contentLength); + } + + updateDownloadSpeed(downloaded - lastDownloaded); + lastDownloaded = downloaded; + } + + updateDownloadSpeed(downloaded - lastDownloaded); + + if (contentLength >= 0 && downloaded != contentLength) + throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); + + if (isCancelled()) break download; + + context.withResult(true); + } + + return; + } catch (IOException ex) { + failedURL = url; + exception = ex; + Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (++repeat), ex); + } + } + } + + if (exception != null) + throw new DownloadException(failedURL, exception); + } + + private static final Timer timer = new Timer("DownloadSpeedRecorder", true); + private static final AtomicInteger downloadSpeed = new AtomicInteger(0); + public static final EventBus speedEvent = new EventBus(); + + static { + timer.schedule(new TimerTask() { + @Override + public void run() { + speedEvent.channel(SpeedEvent.class).fireEvent(new SpeedEvent(speedEvent, downloadSpeed.getAndSet(0))); + } + }, 0, 1000); + } + + private static void updateDownloadSpeed(int speed) { + downloadSpeed.addAndGet(speed); + } + + public static class SpeedEvent extends Event { + private final int speed; + + public SpeedEvent(Object source, int speed) { + super(source); + + this.speed = speed; + } + + /** + * Download speed in byte/sec. + * @return download speed + */ + public int getSpeed() { + return speed; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("speed", speed).toString(); + } + } + + protected static abstract class Context implements Closeable { + private boolean success; + + public abstract void write(byte[] buffer, int offset, int len) throws IOException; + + public final void withResult(boolean success) { + this.success = success; + } + + protected boolean isSuccess() { + return success; + } + } + + protected enum EnumCheckETag { + CHECK_E_TAG, + NOT_CHECK_E_TAG, + CACHED + } +} 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 f72d95bb44..33bd26cc92 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -17,26 +17,23 @@ */ package org.jackhuang.hmcl.task; -import org.jackhuang.hmcl.event.Event; -import org.jackhuang.hmcl.event.EventBus; -import org.jackhuang.hmcl.util.CacheRepository; import org.jackhuang.hmcl.util.Logging; -import org.jackhuang.hmcl.util.ToStringBuilder; -import org.jackhuang.hmcl.util.io.*; +import org.jackhuang.hmcl.util.io.ChecksumMismatchException; +import org.jackhuang.hmcl.util.io.CompressingUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.math.BigInteger; -import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLConnection; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import static java.util.Objects.requireNonNull; @@ -47,7 +44,7 @@ * * @author huangyuhui */ -public class FileDownloadTask extends Task { +public class FileDownloadTask extends FetchTask { public static class IntegrityCheck { private String algorithm; @@ -83,13 +80,9 @@ public void performCheck(MessageDigest digest) throws ChecksumMismatchException } } - private final List urls; private final File file; private final IntegrityCheck integrityCheck; - private final int retry; private Path candidate; - private boolean caching; - private CacheRepository repository = CacheRepository.getInstance(); private RandomAccessFile rFile; private InputStream stream; private final ArrayList integrityCheckHandlers = new ArrayList<>(); @@ -148,35 +141,11 @@ public FileDownloadTask(List urls, File file, IntegrityCheck integrityCheck * @param retry the times for retrying if downloading fails. */ public FileDownloadTask(List urls, File file, IntegrityCheck integrityCheck, int retry) { - if (urls == null || urls.isEmpty()) - throw new IllegalArgumentException("At least one URL is required"); - - this.urls = new ArrayList<>(urls); + super(urls, retry); this.file = file; this.integrityCheck = integrityCheck; - this.retry = retry; setName(file.getName()); - setExecutor(Schedulers.io()); - } - - private void closeFiles() { - if (rFile != null) - try { - rFile.close(); - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Failed to close file: " + rFile, e); - } - - rFile = null; - - if (stream != null) - try { - stream.close(); - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Failed to close stream", e); - } - stream = null; } public File getFile() { @@ -188,217 +157,105 @@ public FileDownloadTask setCandidate(Path candidate) { return this; } - public FileDownloadTask setCaching(boolean caching) { - this.caching = caching; - return this; - } - - public FileDownloadTask setCacheRepository(CacheRepository repository) { - this.repository = repository; - return this; - } - public void addIntegrityCheckHandler(IntegrityCheckHandler handler) { integrityCheckHandlers.add(Objects.requireNonNull(handler)); } @Override - public void execute() throws Exception { - boolean checkETag; + protected EnumCheckETag shouldCheckETag() { // Check cache if (integrityCheck != null && caching) { - checkETag = false; Optional cache = repository.checkExistentFile(candidate, integrityCheck.getAlgorithm(), integrityCheck.getChecksum()); if (cache.isPresent()) { try { FileUtils.copyFile(cache.get().toFile(), file); Logging.LOG.log(Level.FINER, "Successfully verified file " + file + " from " + urls.get(0)); - return; + return EnumCheckETag.CACHED; } catch (IOException e) { Logging.LOG.log(Level.WARNING, "Failed to copy cache files", e); } } + return EnumCheckETag.NOT_CHECK_E_TAG; } else { - checkETag = true; + return EnumCheckETag.CHECK_E_TAG; } + } - Exception exception = null; - URL failedURL = null; - - int repeat = 0; - download: for (URL url : urls) { - for (int retryTime = 0; retryTime < retry; retryTime++) { - if (isCancelled()) { - break download; - } - - Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file); - Path temp = null; - - try { - updateProgress(0); - - HttpURLConnection con = NetworkUtils.createConnection(url); - if (checkETag) repository.injectConnection(con); - con = NetworkUtils.resolveConnection(con); - - if (con.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { - // Handle cache - try { - Path cache = repository.getCachedRemoteFile(con); - FileUtils.copyFile(cache.toFile(), file); - return; - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Unable to use cached file, redownload it", e); - repository.removeRemoteEntry(con); - // Now we must reconnect the server since 304 may result in empty content, - // if we want to redownload the file, we must reconnect the server without etag settings. - retryTime--; - continue; - } - } else if (con.getResponseCode() / 100 == 4) { - break; // we will not try this URL again - } else if (con.getResponseCode() / 100 != 2) { - throw new ResponseCodeException(url, con.getResponseCode()); - } - - int contentLength = con.getContentLength(); - if (contentLength < 0) - throw new IOException("The content length is invalid."); - - if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) - throw new IOException("Could not make directory " + file.getAbsoluteFile().getParent()); - - temp = Files.createTempFile(null, null); - rFile = new RandomAccessFile(temp.toFile(), "rw"); - - MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest(); + @Override + protected void beforeDownload(URL url) { + Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file); + } - stream = con.getInputStream(); - int lastDownloaded = 0, downloaded = 0; - byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; - while (true) { - if (isCancelled()) { - break; - } + @Override + protected void useCachedResult(Path cache) throws IOException { + FileUtils.copyFile(cache.toFile(), file); + } - int read = stream.read(buffer); - if (read == -1) - break; + @Override + protected Context getContext(URLConnection conn, boolean checkETag) throws IOException { + Path temp = Files.createTempFile(null, null); + RandomAccessFile rFile = new RandomAccessFile(temp.toFile(), "rw"); + MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest(); - if (digest != null) { - digest.update(buffer, 0, read); - } + return new Context() { + @Override + public void write(byte[] buffer, int offset, int len) throws IOException { + if (digest != null) { + digest.update(buffer, offset, len); + } - // Write buffer to file. - rFile.write(buffer, 0, read); - downloaded += read; + rFile.write(buffer, offset, len); + } - // Update progress information per second - updateProgress(downloaded, contentLength); + @Override + public void close() throws IOException { + try { + rFile.close(); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Failed to close file: " + rFile, e); + } - updateDownloadSpeed(downloaded - lastDownloaded); - lastDownloaded = downloaded; + if (!isSuccess()) { + try { + Files.delete(temp); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Failed to delete file: " + rFile, e); } + return; + } - updateDownloadSpeed(downloaded - lastDownloaded); - - closeFiles(); + for (IntegrityCheckHandler handler : integrityCheckHandlers) { + handler.checkIntegrity(temp, file.toPath()); + } - if (downloaded != contentLength) - throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); + Files.deleteIfExists(file.toPath()); + if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) + throw new IOException("Unable to make parent directory " + file); - // Restore temp file to original name. - if (isCancelled()) { - temp.toFile().delete(); - break download; - } + try { + FileUtils.moveFile(temp.toFile(), file); + } catch (Exception e) { + throw new IOException("Unable to move temp file from " + temp + " to " + file, e); + } - for (IntegrityCheckHandler handler : integrityCheckHandlers) { - handler.checkIntegrity(temp, file.toPath()); - } + // Integrity check + if (integrityCheck != null) { + integrityCheck.performCheck(digest); + } - Files.deleteIfExists(file.toPath()); - if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) - throw new IOException("Unable to make parent directory " + file); + if (caching && integrityCheck != null) { try { - FileUtils.moveFile(temp.toFile(), file); - } catch (Exception e) { - throw new IOException("Unable to move temp file from " + temp + " to " + file, e); + repository.cacheFile(file.toPath(), integrityCheck.getAlgorithm(), integrityCheck.getChecksum()); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Failed to cache file", e); } - - // Integrity check - if (integrityCheck != null) { - integrityCheck.performCheck(digest); - } - - if (caching && integrityCheck != null) { - try { - repository.cacheFile(file.toPath(), integrityCheck.getAlgorithm(), integrityCheck.getChecksum()); - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Failed to cache file", e); - } - } - - if (checkETag) { - repository.cacheRemoteFile(file.toPath(), con); - } - - return; - } catch (IOException e) { - if (temp != null) - temp.toFile().delete(); - failedURL = url; - exception = e; - Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (++repeat), e); - } finally { - closeFiles(); } - } - } - - if (exception != null) - throw new DownloadException(failedURL, exception); - } - private static final Timer timer = new Timer("DownloadSpeedRecorder", true); - private static final AtomicInteger downloadSpeed = new AtomicInteger(0); - public static final EventBus speedEvent = new EventBus(); - - static { - timer.schedule(new TimerTask() { - @Override - public void run() { - speedEvent.channel(SpeedEvent.class).fireEvent(new SpeedEvent(speedEvent, downloadSpeed.getAndSet(0))); + if (checkETag) { + repository.cacheRemoteFile(file.toPath(), conn); + } } - }, 0, 1000); - } - - private static void updateDownloadSpeed(int speed) { - downloadSpeed.addAndGet(speed); - } - - public static class SpeedEvent extends Event { - private final int speed; - - public SpeedEvent(Object source, int speed) { - super(source); - - this.speed = speed; - } - - /** - * Download speed in byte/sec. - * @return download speed - */ - public int getSpeed() { - return speed; - } - - @Override - public String toString() { - return new ToStringBuilder(this).append("speed", speed).toString(); - } + }; } public interface IntegrityCheckHandler { 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 5ebe123f09..c47efda2c3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -17,23 +17,15 @@ */ package org.jackhuang.hmcl.task; -import org.jackhuang.hmcl.util.CacheRepository; -import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.IOUtils; -import org.jackhuang.hmcl.util.io.NetworkUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; +import java.util.*; import static java.nio.charset.StandardCharsets.UTF_8; @@ -41,12 +33,9 @@ * * @author huangyuhui */ -public final class GetTask extends Task { +public final class GetTask extends FetchTask { - private final List urls; private final Charset charset; - private final int retry; - private CacheRepository repository = CacheRepository.getInstance(); public GetTask(URL url) { this(url, UTF_8); @@ -65,68 +54,35 @@ public GetTask(List url) { } public GetTask(List urls, Charset charset, int retry) { - this.urls = new ArrayList<>(urls); + super(urls, retry); this.charset = charset; - this.retry = retry; setName(urls.get(0).toString()); - setExecutor(Schedulers.io()); } - public GetTask setCacheRepository(CacheRepository repository) { - this.repository = repository; - return this; + @Override + protected EnumCheckETag shouldCheckETag() { + return EnumCheckETag.CHECK_E_TAG; } @Override - public void execute() throws Exception { - Exception exception = null; - URL failedURL = null; - boolean checkETag = true; - for (int time = 0; time < retry * urls.size(); ++time) { - URL url = urls.get(time / retry); - if (isCancelled()) { - break; - } - - try { - updateProgress(0); - HttpURLConnection conn = NetworkUtils.createConnection(url); - if (checkETag) repository.injectConnection(conn); - conn = NetworkUtils.resolveConnection(conn); - - if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { - // Handle cache - try { - Path cache = repository.getCachedRemoteFile(conn); - setResult(FileUtils.readText(cache)); - return; - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Unable to use cached file, redownload it", e); - repository.removeRemoteEntry(conn); - continue; - } - } else if (conn.getResponseCode() / 100 != 2) { - throw new IOException("Server error, response code: " + conn.getResponseCode()); - } - - InputStream input = conn.getInputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; - int size = conn.getContentLength(), read = 0, len; - while ((len = input.read(buf)) != -1) { - baos.write(buf, 0, len); - read += len; + protected void useCachedResult(Path cachedFile) throws IOException { + setResult(FileUtils.readText(cachedFile)); + } - if (size >= 0) - updateProgress(read, size); + @Override + protected Context getContext(URLConnection conn, boolean checkETag) { + return new Context() { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - if (Thread.currentThread().isInterrupted()) - return; - } + @Override + public void write(byte[] buffer, int offset, int len) { + baos.write(buffer, offset, len); + } - if (size > 0 && size != read) - throw new IOException("Not completed! Readed: " + read + ", total size: " + size); + @Override + public void close() throws IOException { + if (!isSuccess()) return; String result = baos.toString(charset.name()); setResult(result); @@ -134,15 +90,8 @@ public void execute() throws Exception { if (checkETag) { repository.cacheText(result, conn); } - return; - } catch (IOException ex) { - failedURL = url; - exception = ex; - Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (time + 1), ex); } - } - if (exception != null) - throw new DownloadException(failedURL, exception); + }; } } 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 ddb02d7c71..54d32264db 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -310,7 +310,7 @@ public ReadOnlyDoubleProperty progressProperty() { return progress.getReadOnlyProperty(); } - protected void updateProgress(int progress, int total) { + protected void updateProgress(long progress, long total) { updateProgress(1.0 * progress / total); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java index 13e22294d4..0f58686d75 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java @@ -54,14 +54,18 @@ public static String withQuery(String baseUrl, Map params) { return sb.toString(); } - public static HttpURLConnection createConnection(URL url) throws IOException { - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + public static URLConnection createConnection(URL url) throws IOException { + URLConnection connection = url.openConnection(); connection.setUseCaches(false); connection.setConnectTimeout(15000); connection.setReadTimeout(15000); return connection; } + public static HttpURLConnection createHttpConnection(URL url) throws IOException { + return (HttpURLConnection) createConnection(url); + } + /** * @see Curl * @param location the url to be URL encoded @@ -129,7 +133,7 @@ public static HttpURLConnection resolveConnection(HttpURLConnection conn) throws } public static String doGet(URL url) throws IOException { - HttpURLConnection con = createConnection(url); + HttpURLConnection con = createHttpConnection(url); con = resolveConnection(con); return IOUtils.readFullyAsString(con.getInputStream()); } @@ -151,7 +155,7 @@ public static String doPost(URL u, String post) throws IOException { public static String doPost(URL url, String post, String contentType) throws IOException { byte[] bytes = post.getBytes(UTF_8); - HttpURLConnection con = createConnection(url); + HttpURLConnection con = createHttpConnection(url); con.setRequestMethod("POST"); con.setDoOutput(true); con.setRequestProperty("Content-Type", contentType + "; charset=utf-8"); @@ -176,7 +180,7 @@ public static String readData(HttpURLConnection con) throws IOException { } public static String detectFileName(URL url) throws IOException { - HttpURLConnection conn = resolveConnection(createConnection(url)); + HttpURLConnection conn = resolveConnection(createHttpConnection(url)); int code = conn.getResponseCode(); if (code / 100 == 4) throw new FileNotFoundException(); @@ -214,7 +218,7 @@ public static boolean isURL(String str) { } public static boolean urlExists(URL url) throws IOException { - HttpURLConnection con = createConnection(url); + HttpURLConnection con = createHttpConnection(url); con = resolveConnection(con); int responseCode = con.getResponseCode(); con.disconnect(); From 3ae1c3467b7713d154f1c34abda61d865b74eee2 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 20:18:43 +0800 Subject: [PATCH 0371/2639] fix: IllegalArgumentException --- .../java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java index 3a37eeb7a6..17caf14cda 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java @@ -49,9 +49,6 @@ public MinecraftInstanceTask(File zipFile, Charset encoding, String subDirectory this.manifest = manifest; this.jsonFile = jsonFile; this.type = type; - - if (!zipFile.exists()) - throw new IllegalArgumentException("File " + zipFile + " does not exist. Cannot parse this modpack."); } @Override From b2693cd3f96847c9433467f6c303a2b3f38a3a5c Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 20:25:35 +0800 Subject: [PATCH 0372/2639] fix: show crashreport instead of a warning of corruption --- .../org/jackhuang/hmcl/game/TexturesLoader.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index 8f9d6a7420..e5b4dc1852 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -24,7 +24,11 @@ import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.ServerResponseMalformedException; -import org.jackhuang.hmcl.auth.yggdrasil.*; +import org.jackhuang.hmcl.auth.yggdrasil.Texture; +import org.jackhuang.hmcl.auth.yggdrasil.TextureModel; +import org.jackhuang.hmcl.auth.yggdrasil.TextureType; +import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; +import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.StringUtils; @@ -35,14 +39,10 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.util.EnumMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -142,8 +142,8 @@ public static LoadedTexture loadTexture(Texture texture) throws IOException { private static void loadDefaultSkin(String path, TextureModel model) { try (InputStream in = ResourceNotFoundError.getResourceAsStream(path)) { DEFAULT_SKINS.put(model, new LoadedTexture(ImageIO.read(in), singletonMap("model", model.modelName))); - } catch (IOException e) { - throw new UncheckedIOException(e); + } catch (Throwable e) { + throw new ResourceNotFoundError("Cannoot load default skin from " + path, e); } } From 4f704653954d2ddd6455292cd0720501980aebce Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 21:41:58 +0800 Subject: [PATCH 0373/2639] fix: crash when JavaSoft registries are malformed. --- .../java/org/jackhuang/hmcl/util/platform/JavaVersion.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java index aad6e63f57..c18310be6c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -259,7 +260,11 @@ private static List queryJavaHomesInRegistryKey(String location) throws IO continue; String home = queryRegisterValue(java, "JavaHome"); if (home != null) { - homes.add(Paths.get(home)); + try { + homes.add(Paths.get(home)); + } catch (InvalidPathException e) { + LOG.log(Level.WARNING, "Invalid Java path in system registry: " + home); + } } } return homes; From 94db91b7c17a544dbd07d9eb6337ddf7a9fc536f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 21:44:51 +0800 Subject: [PATCH 0374/2639] fix: f**king ZipFileSystem --- .../main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java index 265826c829..38b412da48 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/CompressingUtils.java @@ -77,6 +77,8 @@ public FileVisitResult preVisitDirectory(Path dir, return testZipPath(dir, root, result); } }); + } catch (IllegalArgumentException e) { + throw new IOException(e); } return result.get(); } From 8997895a82d61bf8079bf2796d5bd2e593d2dd9a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 21:48:21 +0800 Subject: [PATCH 0375/2639] fix: IllegalArgumentException --- .../java/org/jackhuang/hmcl/ui/construct/FileItem.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 9ecdc2ede9..83f2c55327 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 @@ -75,7 +75,13 @@ public FileItem() { * Converts the given path to absolute/relative(if possible) path according to {@link #convertToRelativePathProperty()}. */ private String processPath(String path) { - Path given = Paths.get(path).toAbsolutePath(); + Path given; + try { + given = Paths.get(path).toAbsolutePath(); + } catch (IllegalArgumentException e) { + return path; + } + if (isConvertToRelativePath()) { try { return Paths.get(".").normalize().toAbsolutePath().relativize(given).normalize().toString(); From 8e9f706d37e872334714394b78acc1d83abd11cf Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 21:56:05 +0800 Subject: [PATCH 0376/2639] fix: VersionNotFoundException --- .../java/org/jackhuang/hmcl/ui/versions/VersionPage.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index 357dbb4b21..008bd8674b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -124,6 +124,14 @@ public void setVersion(String version, Profile profile) { } public void loadVersion(String version, Profile profile) { + // If we jumped to game list page and deleted this version + // and back to this page, we should return to main page. + if (!this.profile.getRepository().isLoaded() || + !this.profile.getRepository().hasVersion(version)) { + Platform.runLater(() -> fireEvent(new PageCloseEvent())); + return; + } + setVersion(version, profile); preferredVersionName = version; listView.getSelectionModel().select(version); From b53a3ebcc2a361339b647e70d73aff8c09afad78 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 29 Apr 2020 22:58:25 +0800 Subject: [PATCH 0377/2639] alt: add logs to figure out the reason why app crashes. --- .../org/jackhuang/hmcl/ui/wizard/WizardController.java | 5 +++++ .../java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java index bcaa92a07e..702cf4ec62 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java @@ -19,6 +19,7 @@ import javafx.scene.Node; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Logging; import java.util.*; @@ -63,6 +64,8 @@ public void onStart() { ((WizardPage) page).onNavigate(settings); displayer.onStart(); + + Logging.LOG.info("Navigating to " + page + ", pages: " + pages); displayer.navigateTo(page, NavigationDirection.START); } @@ -77,6 +80,7 @@ public void onNext(Node page) { if (page instanceof WizardPage) ((WizardPage) page).onNavigate(settings); + Logging.LOG.info("Navigating to " + page + ", pages: " + pages); displayer.navigateTo(page, NavigationDirection.NEXT); } @@ -99,6 +103,7 @@ public void onPrev(boolean cleanUp) { if (prevPage instanceof WizardPage) ((WizardPage) prevPage).onNavigate(settings); + Logging.LOG.info("Navigating to " + prevPage + ", pages: " + pages); displayer.navigateTo(prevPage, NavigationDirection.PREVIOUS); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java index 6cadd3d856..a3b28474b4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java @@ -22,12 +22,12 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; -import java.util.Collection; -import java.util.Collections; +import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; import java.util.logging.Level; /** @@ -56,7 +56,8 @@ public TaskExecutor start() { Throwable resolvedException = resolveException(exception); if (resolvedException instanceof RuntimeException && !(resolvedException instanceof CancellationException) && - !(resolvedException instanceof JsonParseException)) { + !(resolvedException instanceof JsonParseException) && + !(resolvedException instanceof RejectedExecutionException)) { // Track uncaught RuntimeException which are thrown mostly by our mistake if (uncaughtExceptionHandler != null) uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), resolvedException); From 7c510f9fb8655598a26b1b5937bcb0046d0960d4 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 3 May 2020 19:21:54 +0800 Subject: [PATCH 0378/2639] add: allow installing OptiFine 1.14.4 and Forge in same game version --- .gitignore | 3 + HMCL/build.gradle | 8 ++- .../hmcl/game/HMCLGameRepository.java | 5 +- .../jackhuang/hmcl/game/LauncherHelper.java | 15 ++++- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_es.properties | 1 + .../resources/assets/lang/I18N_ru.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../hmcl/download/LibraryAnalyzer.java | 4 ++ .../jackhuang/hmcl/download/MaintainTask.java | 57 ++++++++++++++---- .../hmcl/download/forge/ForgeInstallTask.java | 3 +- .../liteloader/LiteLoaderInstallTask.java | 2 +- .../optifine/OptiFineInstallTask.java | 6 +- .../hmcl/game/DefaultGameRepository.java | 7 ++- .../jackhuang/hmcl/game/GameRepository.java | 2 + .../hmcl/game/VersionLibraryBuilder.java | 25 ++++++-- .../hmcl/launch/DefaultLauncher.java | 1 + .../HMCLTransformerDiscoveryService-1.0.jar | Bin 0 -> 2243 bytes ...er.serviceapi.ITransformerDiscoveryService | 1 + HMCLTransformerDiscoveryService/build.gradle | 12 ++++ .../lib/modlauncher-4.1.0.jar | Bin 0 -> 115195 bytes .../hmcl/HMCLTransformerDiscoveryService.java | 44 ++++++++++++++ ...er.serviceapi.ITransformerDiscoveryService | 1 + build.gradle | 1 - settings.gradle | 1 + 26 files changed, 176 insertions(+), 27 deletions(-) create mode 100644 HMCLCore/src/main/resources/assets/game/HMCLTransformerDiscoveryService-1.0.jar create mode 100644 HMCLTransformerDiscoveryService/bin/main/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService create mode 100644 HMCLTransformerDiscoveryService/build.gradle create mode 100644 HMCLTransformerDiscoveryService/lib/modlauncher-4.1.0.jar create mode 100644 HMCLTransformerDiscoveryService/src/main/java/org/jackhuang/hmcl/HMCLTransformerDiscoveryService.java create mode 100644 HMCLTransformerDiscoveryService/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService diff --git a/.gitignore b/.gitignore index 760c29d964..5e6b85816d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,17 +17,20 @@ NVIDIA /build/ /HMCL/build/ /HMCLCore/build/ +/HMCLTransformerDiscoveryService/build/ # idea .idea /out/ /HMCL/out/ /HMCLCore/out/ +/HMCLTransformerDiscoveryService/out/ # eclipse /bin/ /HMCL/bin/ /HMCLCore/bin/ +/HMCLTransformerDiscoveryService/bin/ .classpath .project .settings diff --git a/HMCL/build.gradle b/HMCL/build.gradle index 16d1bdb20a..917cf3bfa8 100644 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -1,3 +1,9 @@ +buildscript { + dependencies { + classpath 'org.tukaani:xz:1.8' + } +} + plugins { id 'com.github.johnrengelman.shadow' version '4.0.0' id 'application' @@ -77,7 +83,7 @@ def repack(File file) { jar { manifest { - attributes 'Created-By': 'Copyright(c) 2013-2018 huangyuhui.', + attributes 'Created-By': 'Copyright(c) 2013-2020 huangyuhui.', 'Main-Class': mainClassName, 'Multi-Release': 'true', 'Implementation-Version': version 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 b6789d7d5b..a6181ddbf7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -20,6 +20,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import javafx.scene.image.Image; +import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; @@ -218,9 +219,9 @@ public Image getVersionIconImage(String id) { if (iconFile.exists()) return new Image("file:" + iconFile.getAbsolutePath()); else if (version.getMainClass() != null && - ("net.minecraft.launchwrapper.Launch".equals(version.getMainClass()) + (LibraryAnalyzer.LAUNCH_WRAPPER_MAIN.equals(version.getMainClass()) || version.getMainClass().startsWith("net.fabricmc") - || "cpw.mods.modlauncher.Launcher".equals(version.getMainClass()))) + || LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(version.getMainClass()))) return newImage("/assets/img/furnace.png"); else return newImage("/assets/img/grass.png"); 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 fa78440e89..b5706a9242 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException; import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; import org.jackhuang.hmcl.download.game.LibraryDownloadException; @@ -330,7 +331,7 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers // LaunchWrapper 1.12 will crash because of assuming the system class loader is an instance of URLClassLoader. if (!flag && java.getParsedVersion() >= JavaVersion.JAVA_9_AND_LATER - && version.getMainClass().contains("launchwrapper") + && version.getMainClass().equals(LibraryAnalyzer.LAUNCH_WRAPPER_MAIN) && version.getLibraries().stream() .filter(library -> "launchwrapper".equals(library.getArtifactId())) .anyMatch(library -> VersionNumber.asVersion(library.getVersion()).compareTo(VersionNumber.asVersion("1.13")) < 0)) { @@ -421,6 +422,18 @@ private static void checkGameState(Profile profile, VersionSetting setting, Vers } } + // OptiFine 1.14.4 is not compatible with Forge 28.2.2 and later versions. + if (!flag) { + boolean hasForge28_2_2 = version.getLibraries().stream().filter(it -> it.is("net.minecraftforge", "forge")) + .anyMatch(it -> + VersionNumber.VERSION_COMPARATOR.compare("1.14.4-28.2.2", it.getVersion()) <= 0); + boolean hasOptiFine = version.getLibraries().stream().anyMatch(it -> it.is("optifine", "OptiFine")); + if (hasForge28_2_2 && hasOptiFine && gameVersion.compareTo(VersionNumber.asVersion("1.14.4")) == 0) { + Controllers.confirm(i18n("launch.advice.forge28_2_2_optifine"), i18n("message.error"), onAccept, null); + flag = true; + } + } + if (!flag) onAccept.run(); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index b1358b5d32..706e0ba9e4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -169,6 +169,7 @@ launch.advice.corrected=We have already fixed the JVM selection. If you want to launch.advice.uncorrected=If you are sure that the game can be started normally, you can disable the Java VM check in game settings. launch.advice.different_platform=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. launch.advice.forge2760_liteloader=Forge 2760 and higher are not compatible with LiteLoader, please consider upgrading Forge to 2773 or later. Shall we continue launching? +launch.advice.forge28_2_2_optifine=Forge 28.2.2 and later versions are not compatible with OptiFine. Please consider downgrading Forge to 28.2.1 or earlier versions. Shall we continue launching? launch.advice.java8_1_13=Minecraft 1.13 and later can only run on Java 8 or later. launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 earlier than 1.8.0_51. Please install the latest version of Java 8. launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later versions of Java. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index c29131074e..7e6452fe16 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -165,6 +165,7 @@ launch.advice.corrected=Ya hemos corregido la selección de JVM y el juego puede launch.advice.uncorrected=Si está seguro que el juego puede ser lanzado normalmente, puede deshabilitar el Java VM checker en la configuración del juego. launch.advice.different_platform=Su SO es 64-Bit pero su Java es 32-Bit. 64-Bit Java es recomendado. launch.advice.forge2760_liteloader=Forge 2760 y posterior no es compatible con LiteLoader, considere actualizando Forge a 2773 o más. +launch.advice.forge28_2_2_optifine=Forge 28.2.2 and later versions are not compatible with OptiFine. Please consider downgrading Forge to 28.2.1 or earlier versions. Shall we continue launching? launch.advice.java8_1_13=Minecraft 1.13 y posterior sólo pueden correr en Java 8 o luego. launch.advice.java8_51_1_13=Minecraft 1.13 puediera fallar en Java 8 anterior 1.8.0_51. Debe instalar la versión de Java 8 más reciente. launch.advice.java9=No puedes lanzar Minecraft hasta que su versión de juego sea más allá de 1.13 con Java 9 o posterior. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index de720a3f56..122945d361 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -169,6 +169,7 @@ launch.advice.corrected=Мы уже исправили выбор JVMЕ. Есл launch.advice.uncorrected=Если вы уверены, что игра запускается нормально, то можете отключить проверку Java VM в настройках игры. launch.advice.different_platform=Ваша ОС 64-битная, а ваша Java 32-битная. Рекомендуется использовать 64-битный Java. launch.advice.forge2760_liteloader=Forge 2760 и выше не совместимы с LiteLoader, рассмотрите возможность обновления Forge до 2773 или более поздней версии. +launch.advice.forge28_2_2_optifine=Forge 28.2.2 and later versions are not compatible with OptiFine. Please consider downgrading Forge to 28.2.1 or earlier versions. Shall we continue launching? launch.advice.java8_1_13=Minecraft 1.13 и выше может работать только на Java 8 или более поздней версии. launch.advice.java8_51_1_13=У Minecraft 1.13 может произойти сбой на Java 8 меньше, чем 1.8.0_51. Установите последнюю версию Java 8. launch.advice.java9=Вы не можете запустить Minecraft 1.12 или более ранней версии с Java 9 или более новых версий Java. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index e2bf3f512b..034b1f0a30 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -169,6 +169,7 @@ launch.advice.corrected=我們已經修正了問題。如果您確實希望使 launch.advice.uncorrected=如果您確實希望使用您自訂的 Java 虛擬機,您可以在遊戲設定中關閉 Java 虛擬機相容性檢查。 launch.advice.different_platform=您的系統為 64 位元,但是 Java 是 32 位元,建議您安裝 64 位 Java。 launch.advice.forge2760_liteloader=Forge 2760 與 LiteLoader 不相容。請刪除 LiteLoader 或者變更 Forge 至 2773 或更新的版本。是否繼續啟動? +launch.advice.forge28_2_2_optifine=Forge 28.2.2 或更高版本與 OptiFine 不相容。請變更 Forge 至 28.2.1 或更低版本。是否繼續啟動? launch.advice.java8_1_13=Minecraft 1.13 只支援 Java 8 或更高版本,請使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低於 1.8.0_51 的 Java 版本可能會導致 Minecraft 1.13 崩潰。建議您到 https://java.com 安裝最新版的 Java 8。 launch.advice.java9=低於 (包含) 1.13 的有安裝 Mod 的 Minecraft 版本不支援 Java 9 或更高版本,請使用 Java 8。 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 e6b2b639f7..f33e891f1b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -169,6 +169,7 @@ launch.advice.corrected=我们已经修复了问题。如果您确实希望使 launch.advice.uncorrected=如果您确实希望使用您自定义的 Java 虚拟机,您可以在游戏设置中关闭 Java 虚拟机兼容性检查。 launch.advice.different_platform=您的系统是 64 位,但是 Java 是 32 位的,建议您安装 64 位 Java。 launch.advice.forge2760_liteloader=Forge 2760 与 LiteLoader 不兼容。请删除 LiteLoader 或者更换 Forge 至 2773 或更新的版本。是否继续启动? +launch.advice.forge28_2_2_optifine=Forge 28.2.2 或更高版本与 OptiFine 不兼容。请更换 Forge 至 28.2.1 或更低版本。是否继续启动? launch.advice.java8_1_13=Minecraft 1.13 只支持 Java 8 或更高版本,请使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低于 1.8.0_51 的 Java 版本可能会导致 Minecraft 1.13 崩溃。建议您到 https://java.com 安装最新版的 Java 8。 launch.advice.java9=低于 1.13 的有安装 Mod 的 Minecraft 版本不支持 Java 9 或更高版本,请使用 Java 8。 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index 2486226730..d7f2ac419f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -198,4 +198,8 @@ public String getLibraryVersion() { return libraryVersion; } } + + public static final String VANILLA_MAIN = "net.minecraft.client.main.Main"; + public static final String LAUNCH_WRAPPER_MAIN = "net.minecraft.launchwrapper.Launch"; + public static final String MOD_LAUNCHER_MAIN = "cpw.mods.modlauncher.Launcher"; } 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 7d91f48c3a..82de9d81d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -24,18 +24,22 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.game.VersionLibraryBuilder; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.SimpleMultimap; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.versioning.VersionNumber; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.*; +import java.util.logging.Level; import java.util.stream.Collectors; -import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.FORGE; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.LITELOADER; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.OPTIFINE; public class MaintainTask extends Task { private final GameRepository repository; @@ -60,13 +64,15 @@ public static Version maintain(GameRepository repository, Version version) { String mainClass = version.resolve(null).getMainClass(); - if (mainClass != null && mainClass.contains("launchwrapper")) { - return maintainOptiFineLibrary(repository, maintainGameWithLaunchWrapper(unique(version), true)); + if (mainClass != null && mainClass.equals(LibraryAnalyzer.LAUNCH_WRAPPER_MAIN)) { + return maintainOptiFineLibrary(repository, maintainGameWithLaunchWrapper(unique(version), true), false); + } else if (mainClass != null && mainClass.equals(LibraryAnalyzer.MOD_LAUNCHER_MAIN)) { + // Forge 1.13 and OptiFine + return maintainOptiFineLibrary(repository, maintainGameWithModLauncher(repository, unique(version)), true); } else { // Vanilla Minecraft does not need maintain - // Forge 1.13 support not implemented, not compatible with OptiFine currently. // Fabric does not need maintain, nothing compatible with fabric now. - return maintainOptiFineLibrary(repository, unique(version)); + return maintainOptiFineLibrary(repository, unique(version), false); } } @@ -116,7 +122,34 @@ private static Version maintainGameWithLaunchWrapper(Version version, boolean re return mainClass == null ? ret : ret.setMainClass(mainClass); } - private static Version maintainOptiFineLibrary(GameRepository repository, Version version) { + private static Version maintainGameWithModLauncher(GameRepository repository, Version version) { + LibraryAnalyzer libraryAnalyzer = LibraryAnalyzer.analyze(version); + VersionLibraryBuilder builder = new VersionLibraryBuilder(version); + + if (!libraryAnalyzer.has(FORGE)) return version; + + if (libraryAnalyzer.has(OPTIFINE)) { + Library hmclTransformerDiscoveryService = new Library(new Artifact("org.jackhuang.hmcl", "transformer-discovery-service", "1.0")); + Optional optiFine = version.getLibraries().stream().filter(library -> library.is("optifine", "OptiFine")).findAny(); + boolean libraryExisting = version.getLibraries().stream().anyMatch(library -> library.is("org.jackhuang.hmcl", "transformer-discovery-service")); + optiFine.ifPresent(library -> { + builder.addJvmArgument("-Dhmcl.transformer.candidates=${libraries_directory}/" + library.getPath()); + if (!libraryExisting) builder.addLibrary(hmclTransformerDiscoveryService); + Path libraryPath = repository.getLibraryFile(version, hmclTransformerDiscoveryService).toPath(); + try { + Files.createDirectories(libraryPath.getParent()); + Files.copy(MaintainTask.class.getResourceAsStream("/assets/game/HMCLTransformerDiscoveryService-1.0.jar"), + libraryPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to unpack HMCLTransformerDiscoveryService", e); + } + }); + } + + return builder.build(); + } + + private static Version maintainOptiFineLibrary(GameRepository repository, Version version, boolean remove) { LibraryAnalyzer libraryAnalyzer = LibraryAnalyzer.analyze(version); List libraries = new ArrayList<>(version.getLibraries()); @@ -135,7 +168,7 @@ private static Version maintainOptiFineLibrary(GameRepository repository, Versio // Although we have altered priority of OptiFine higher than Forge, // there still exists a situation that Forge is installed without patch. // Here we manually alter the position of OptiFine library in classpath. - libraries.add(newLibrary); + if (!remove) libraries.add(newLibrary); } } 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 a558b65cca..943dd7e836 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 @@ -19,6 +19,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.VersionMismatchException; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.GameVersion; @@ -104,7 +105,7 @@ public void execute() throws IOException, VersionMismatchException, OptiFineInst String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) { // Forge 1.13 is not compatible with any other libraries. - if (!"net.minecraft.client.main.Main".equals(originalMainClass) && !"cpw.mods.modlauncher.Launcher".equals(originalMainClass)) + if (!LibraryAnalyzer.VANILLA_MAIN.equals(originalMainClass) && !LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(originalMainClass) && !LibraryAnalyzer.LAUNCH_WRAPPER_MAIN.equals(originalMainClass)) throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); } else { // Forge 1.12 and older versions is compatible with vanilla and launchwrapper. 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 1d5c38b73d..5999fc6fd5 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 @@ -69,7 +69,7 @@ public void execute() { remote.getSelfVersion(), 60000, new Arguments().addGameArguments("--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"), - "net.minecraft.launchwrapper.Launch", + LibraryAnalyzer.LAUNCH_WRAPPER_MAIN, Lang.merge(remote.getLibraries(), Collections.singleton(library))) .setLogging(Collections.emptyMap()) // Mods may log in malformed format, causing XML parser to crash. So we suppress using official log4j configuration ); 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 8764ed495d..97ab70ba5c 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 @@ -121,7 +121,7 @@ public boolean isRelyingOnDependencies() { @Override public void execute() throws Exception { String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); - if (!"net.minecraft.client.main.Main".equals(originalMainClass) && !"net.minecraft.launchwrapper.Launch".equals(originalMainClass)) + if (!LibraryAnalyzer.VANILLA_MAIN.equals(originalMainClass) && !LibraryAnalyzer.LAUNCH_WRAPPER_MAIN.equals(originalMainClass) && !LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(originalMainClass)) throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); List libraries = new LinkedList<>(); @@ -183,9 +183,9 @@ public void execute() throws Exception { setResult(new Version( LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId(), remote.getSelfVersion(), - 90000, + 10000, new Arguments().addGameArguments("--tweakClass", "optifine.OptiFineTweaker"), - "net.minecraft.launchwrapper.Launch", + LibraryAnalyzer.LAUNCH_WRAPPER_MAIN, libraries )); 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 1824a688d8..01a0255e02 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -96,12 +96,17 @@ public Collection getVersions() { return versions.values(); } + @Override + public File getLibrariesDirectory(Version version) { + return new File(getBaseDirectory(), "libraries"); + } + @Override public File getLibraryFile(Version version, Library lib) { if ("local".equals(lib.getHint()) && lib.getFileName() != null) return new File(getVersionRoot(version.getId()), "libraries/" + lib.getFileName()); else - return new File(getBaseDirectory(), "libraries/" + lib.getPath()); + return new File(getLibrariesDirectory(version), lib.getPath()); } public Path getArtifactFile(Version version, Artifact artifact) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java index f32da60067..cefbde81a4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameRepository.java @@ -99,6 +99,8 @@ default Task refreshVersionsAsync() { */ File getRunDirectory(String id); + File getLibrariesDirectory(Version version); + /** * Get the library file in disk. * This method allows versions and libraries that are not loaded by this game repository. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/VersionLibraryBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/VersionLibraryBuilder.java index 275944f3df..272c0aebb4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/VersionLibraryBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/VersionLibraryBuilder.java @@ -20,8 +20,7 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.platform.CommandBuilder; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * @@ -31,12 +30,17 @@ public final class VersionLibraryBuilder { private final Version version; private final List mcArgs; private final List game; + private final List jvm; + private final List libraries; private final boolean useMcArgs; + private boolean jvmChanged = false; public VersionLibraryBuilder(Version version) { this.version = version; + this.libraries = new ArrayList<>(version.getLibraries()); this.mcArgs = version.getMinecraftArguments().map(StringUtils::tokenize).map(ArrayList::new).orElse(null); this.game = version.getArguments().map(Arguments::getGame).map(ArrayList::new).orElseGet(ArrayList::new); + this.jvm = new ArrayList<>(version.getArguments().map(Arguments::getJvm).orElse(Arguments.DEFAULT_JVM_ARGUMENTS)); this.useMcArgs = mcArgs != null; } @@ -47,7 +51,10 @@ public Version build() { // so we regenerate the minecraftArgument without escaping. ret = ret.setMinecraftArguments(new CommandBuilder().addAllWithoutParsing(mcArgs).toString()); } - return ret.setArguments(ret.getArguments().map(args -> args.withGame(game)).orElse(new Arguments(game, null))); + return ret.setArguments(ret.getArguments() + .map(args -> args.withGame(game)) + .map(args -> jvmChanged ? args.withJvm(jvm) : args).orElse(new Arguments(game, jvmChanged ? jvm : null))) + .setLibraries(libraries); } public void removeTweakClass(String target) { @@ -138,8 +145,18 @@ public void replaceTweakClass(String target, String replacement, boolean inPlace } } - public void addArgument(String... args) { + public void addGameArgument(String... args) { for (String arg : args) game.add(new StringArgument(arg)); } + + public void addJvmArgument(String... args) { + jvmChanged = true; + for (String arg : args) + jvm.add(new StringArgument(arg)); + } + + public void addLibrary(Library library) { + libraries.add(library); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index f2d717cd05..148a6fb11d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -153,6 +153,7 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException configuration.put("${natives_directory}", nativeFolder.getAbsolutePath()); configuration.put("${game_assets}", gameAssets.getAbsolutePath()); configuration.put("${assets_root}", gameAssets.getAbsolutePath()); + configuration.put("${libraries_directory}", repository.getLibrariesDirectory(version).getAbsolutePath()); res.addAll(Arguments.parseArguments(version.getArguments().map(Arguments::getJvm).orElseGet(this::getDefaultJVMArguments), configuration)); if (authInfo.getArguments() != null && authInfo.getArguments().getJvm() != null && !authInfo.getArguments().getJvm().isEmpty()) diff --git a/HMCLCore/src/main/resources/assets/game/HMCLTransformerDiscoveryService-1.0.jar b/HMCLCore/src/main/resources/assets/game/HMCLTransformerDiscoveryService-1.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..3ea51be50926e0b72ac87e7c8e73086edbbd6f04 GIT binary patch literal 2243 zcmWIWW@h1HVBp|jNGw|%zyJhHAOZ+Df!NnI#8KDN&rP41Apk|;rh2A#(m(~0KrDi+ z(AUw=)6F$FM9CTC}qCg$N+EsUW$BR4q*!vcTp@ zH?_zmvp6}wEVZaIIJKxOGdWc+IVZ8Wcy3sBxU{Q8omz~TnYX8=h^X$RWhM(!H-@ck z3YBuW;BZkP?p5xlnJUb)@0ONNo>lMq+H%%68QZ#VKW5wP+br#=kh!An#JMxp@1M?m zzIV=_pWiRvXS{RFS$494dm-oP#TCrkOH@8C^Apeaz3|sdXmv&W@z|OLW%5}Omka#e z#a_SKvoJCEuzS{S)23Wm`NzV%mb}(dWs+as+iH=tWv`K(Fd*PO|b9kIKNojvx6)}C^2B+)!20q_5B}<$=z3K4b zS^fs$^G|=z(qFp!$*W0cSGOwpZ-2OKx@2D3u9t60BwO}92rYHyu1sW6sZ~3&E%^C1 zomC#v_K}CUm%g6xYJodbRi>SaSNRU{jlP{}5|LZqgzfvXC;GGQM$J&AOV2m#UGhk( zf>B>;M^7g2ciuONw+<}-;p2SofSp~s$KB$)6AFs+-CIPrOZ4zRR%q4F_-WKy$sGSM zo0p%bra9lVCjCM6pM-|R2MQjVOn>rP$5Kj%*_DG?b&BM=dFNR~W6Ry9SUS!PG~Fh$ zEq>3HbA4==CRwEH_WQXM}YMeBD@icB9rI^X3~()tBzPdwsFP z=92cKl-`wJp0ysY^;11#AX2eyiH3Pq=#}O;-`QE4_dff*$MLVR%ysF*LCY?y)H%*S zbfu7G_uV?%9xGQXU(GJVBev(4-J5;3#7a+4Un~DvTDG&t^7(?(9kp-TEP0f+WAe+_ zOX7pimc*vU-tKd2exy?JIBCzMmk*z~O#YJ*R+A8M?#tyjj+|%P-)Svhf$l2_TQs3)KlQMpGx1SUH zy3tqJ%q-^Rv9CIZ|F)_ByPqnvY5!ZN@43@%m&LU;%~)j|Q@`$efbO^Jhh?_jP?1>n z;`=12YhTn8CVVs5t<0Hl=~RYn)F06|g1JI77QQb~+0!)rW%d!Siq>-r{_4c3>ZZml zFm-%=^|*)4u><-NIY}=xB_DHcVVNaS*>sWRUqfBZqsk@*hU*1_nM_+e1lGF->K&gK z6?i4DudXL=YO2-J)u%EW#n$c!?q=Svc(di=ksF15-yZue=~Ld}*;LEO9O$vNsfYK@ z0SP1ZhsO+@CiyI}Z*A?Ed-TW0FUy~s?yCLUvV5lpx5V5XH;x=R?_txmBcs^V+cD2A zV)}#2t0rG@?vOuu^tP_peZ{%f72@yzG9yY^^g>SvSSG=X<6=mOQ;boHT{eCjV+K@d z0>pk;btD&*>*eOB6oZJI#L~RvjMO4MsCkJ6nR=dhO1RVdUe`~1`J6ka;d{pW`sowC z=PrK!Q2LEi)9Z}3-)a3*zPd#xb^Olhd+V;^@zd2h?c?_pT-Y-*i7?}?WPr{D0s)4% zjvyND#{h3sZRk}FNHGX3Y19OgaBWBx5V8sA!3nBoAOK`>8ITF8b@1r`)jALW(lHCj z1nEH3LHP87>L3UJ={*5tqUr_LNazNj*GMoUmNfpxZU9mB6S^%RQ(;v;D2+h?$eI1D nNWltEap?NdQyk2MC5;EM>Zc_A1$eWvfz0OsLNB1BlfgUyP_HXA literal 0 HcmV?d00001 diff --git a/HMCLTransformerDiscoveryService/bin/main/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService b/HMCLTransformerDiscoveryService/bin/main/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService new file mode 100644 index 0000000000..82fc86968d --- /dev/null +++ b/HMCLTransformerDiscoveryService/bin/main/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService @@ -0,0 +1 @@ +org.jackhuang.hmcl.HMCLTransformerDiscoveryService diff --git a/HMCLTransformerDiscoveryService/build.gradle b/HMCLTransformerDiscoveryService/build.gradle new file mode 100644 index 0000000000..82d65da474 --- /dev/null +++ b/HMCLTransformerDiscoveryService/build.gradle @@ -0,0 +1,12 @@ +version '1.0' + +dependencies { + compileOnly project.files("lib/modlauncher-4.1.0.jar") +} + +jar { + manifest { + attributes 'Created-By': 'Copyright(c) 2013-2020 huangyuhui.', + 'Implementation-Version': version + } +} diff --git a/HMCLTransformerDiscoveryService/lib/modlauncher-4.1.0.jar b/HMCLTransformerDiscoveryService/lib/modlauncher-4.1.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..2dd8cb64e51cee8f2fef2f23c5827fe571ed2534 GIT binary patch literal 115195 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�q+!5JL`6yv#fb4 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 and contributors + * + * 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 . + */ +package org.jackhuang.hmcl; + +import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; + +import java.io.File; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class HMCLTransformerDiscoveryService implements ITransformerDiscoveryService { + private static final String CANDIDATES = System.getProperty("hmcl.transformer.candidates"); + + @Override + public List candidates(Path gameDirectory) { + return Arrays.stream(CANDIDATES.split(File.pathSeparator)) + .flatMap(path -> { + try { + return Stream.of(Paths.get(path)); + } catch (InvalidPathException e) { + return Stream.of(); + } + }).collect(Collectors.toList()); + } +} diff --git a/HMCLTransformerDiscoveryService/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService b/HMCLTransformerDiscoveryService/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService new file mode 100644 index 0000000000..82fc86968d --- /dev/null +++ b/HMCLTransformerDiscoveryService/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService @@ -0,0 +1 @@ +org.jackhuang.hmcl.HMCLTransformerDiscoveryService diff --git a/build.gradle b/build.gradle index bc6c1051ae..f8443b1ce3 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,6 @@ buildscript { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'org.tukaani:xz:1.8' classpath 'gradle.plugin.com.hierynomus.gradle.plugins:license-gradle-plugin:0.15.0' } } diff --git a/settings.gradle b/settings.gradle index d9fd5ba34b..32100c8ffa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,5 @@ rootProject.name = 'HMCL3' include 'HMCL' include 'HMCLCore' +include 'HMCLTransformerDiscoveryService' From e6d11fe9a35cc94ecd8c67b1008cef48f1fb79a4 Mon Sep 17 00:00:00 2001 From: Asnxthaony Date: Sun, 24 May 2020 14:54:07 +0800 Subject: [PATCH 0379/2639] feat: send accept language header --- .../src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java index 0f58686d75..5337bffd44 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java @@ -20,6 +20,7 @@ import java.io.*; import java.net.*; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; @@ -59,6 +60,7 @@ public static URLConnection createConnection(URL url) throws IOException { connection.setUseCaches(false); connection.setConnectTimeout(15000); connection.setReadTimeout(15000); + connection.setRequestProperty("Accept-Language", Locale.getDefault().toString()); return connection; } From 42d42e9750a601dbfb6a9cd5f1621f946147b8e9 Mon Sep 17 00:00:00 2001 From: Yuhui Huang Date: Tue, 26 May 2020 17:19:55 +0800 Subject: [PATCH 0380/2639] fix: #619 --- .../hmcl/mod/curse/CurseCompletionTask.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java index ac62aa2d8d..ee29685e72 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseCompletionTask.java @@ -118,30 +118,36 @@ public void execute() throws Exception { if (StringUtils.isBlank(file.getFileName())) { try { return file.withFileName(NetworkUtils.detectFileName(file.getUrl())); - } catch (FileNotFoundException e) { + } catch (IOException e) { try { String result = NetworkUtils.doGet(NetworkUtils.toURL(String.format("https://cursemeta.dries007.net/%d/%d.json", file.getProjectID(), file.getFileID()))); CurseMetaMod mod = JsonUtils.fromNonNullJson(result, CurseMetaMod.class); return file.withFileName(mod.getFileNameOnDisk()).withURL(mod.getDownloadURL()); + } catch (FileNotFoundException fof) { + Logging.LOG.log(Level.WARNING, "Could not query cursemeta for deleted mods: " + file.getUrl(), fof); + notFound.set(true); + return file; } catch (IOException | JsonParseException e2) { try { String result = NetworkUtils.doGet(NetworkUtils.toURL(String.format("https://addons-ecs.forgesvc.net/api/v2/addon/%d/file/%d", file.getProjectID(), file.getFileID()))); CurseMetaMod mod = JsonUtils.fromNonNullJson(result, CurseMetaMod.class); return file.withFileName(mod.getFileName()).withURL(mod.getDownloadURL()); - } catch (IOException | JsonParseException e3) { - Logging.LOG.log(Level.WARNING, "Could not query cursemeta for deleted mods: " + file.getUrl(), e2); + } catch (FileNotFoundException fof) { + Logging.LOG.log(Level.WARNING, "Could not query forgesvc for deleted mods: " + file.getUrl(), fof); notFound.set(true); return file; + } catch (IOException | JsonParseException e3) { + Logging.LOG.log(Level.WARNING, "Unable to fetch the file name of URL: " + file.getUrl(), e); + Logging.LOG.log(Level.WARNING, "Unable to fetch the file name of URL: " + file.getUrl(), e2); + Logging.LOG.log(Level.WARNING, "Unable to fetch the file name of URL: " + file.getUrl(), e3); + allNameKnown.set(false); + return file; } } - - } catch (IOException ioe) { - Logging.LOG.log(Level.WARNING, "Unable to fetch the file name of URL: " + file.getUrl(), ioe); - allNameKnown.set(false); - return file; } - } else + } else { return file; + } }) .collect(Collectors.toList())); FileUtils.writeText(new File(root, "manifest.json"), JsonUtils.GSON.toJson(newManifest)); From a2ef477ae06d6ef7a4908e6abe9369ded853515f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 31 May 2020 22:24:03 +0800 Subject: [PATCH 0381/2639] add: forbids installation buttons for incompatible libraries. Closes #720. --- .../org/jackhuang/hmcl/ui/InstallerItem.java | 230 +++++++++++++----- .../ui/download/AdditionalInstallersPage.java | 20 +- .../hmcl/ui/download/InstallersPage.java | 92 ++----- .../hmcl/ui/versions/InstallerListPage.java | 54 ++-- .../resources/assets/lang/I18N.properties | 7 +- .../resources/assets/lang/I18N_es.properties | 5 +- .../resources/assets/lang/I18N_ru.properties | 7 +- .../resources/assets/lang/I18N_zh.properties | 7 +- .../assets/lang/I18N_zh_CN.properties | 7 +- .../hmcl/download/forge/ForgeInstallTask.java | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 11 files changed, 249 insertions(+), 184 deletions(-) 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 8de943a90a..c61bb1dab3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -19,94 +19,198 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.effects.JFXDepthManager; +import javafx.beans.binding.Bindings; +import javafx.beans.property.*; +import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.scene.Cursor; +import javafx.scene.control.Control; import javafx.scene.control.Label; +import javafx.scene.control.Skin; +import javafx.scene.control.SkinBase; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.setting.Theme; -import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import org.jackhuang.hmcl.util.i18n.I18n; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; /** * @author huangyuhui */ -public class InstallerItem extends BorderPane { - - public InstallerItem(String libraryId, String libraryVersion, @Nullable Runnable upgrade, @Nullable Consumer deleteCallback) { - getStyleClass().addAll("two-line-list-item", "card"); - JFXDepthManager.setDepth(this, 1); - - String[] urls = new String[]{"/assets/img/grass.png", "/assets/img/fabric.png", "/assets/img/forge.png", "/assets/img/chicken.png", "/assets/img/command.png"}; - String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"}; - - boolean regularLibrary = false; - for (int i = 0; i < 5; ++i) { - if (libraryIds[i].equals(libraryId)) { - setLeft(FXUtils.limitingSize(new ImageView(new Image(urls[i], 32, 32, true, true)), 32, 32)); - Label label = new Label(); - BorderPane.setAlignment(label, Pos.CENTER_LEFT); - BorderPane.setMargin(label, new Insets(0, 0, 0, 8)); - if (libraryVersion == null) { - label.setText(i18n("install.installer.not_installed", i18n("install.installer." + libraryId))); - } else { - label.setText(i18n("install.installer.version", i18n("install.installer." + libraryId), libraryVersion)); - } - setCenter(label); - regularLibrary = true; +public class InstallerItem extends Control { + private final String id; + private final String imageUrl; + public final StringProperty libraryVersion = new SimpleStringProperty(); + public final StringProperty incompatibleLibraryName = new SimpleStringProperty(); + public final BooleanProperty incompatibleWithGame = new SimpleBooleanProperty(); + public final BooleanProperty removable = new SimpleBooleanProperty(); + public final BooleanProperty upgradable = new SimpleBooleanProperty(false); + public final BooleanProperty installable = new SimpleBooleanProperty(true); + public final ObjectProperty> removeAction = new SimpleObjectProperty<>(); + public final ObjectProperty> action = new SimpleObjectProperty<>(); + + public InstallerItem(LibraryAnalyzer.LibraryType id) { + this(id.getPatchId()); + } + + public InstallerItem(String id) { + this.id = id; + + switch (id) { + case "game": + imageUrl = "/assets/img/grass.png"; + break; + case "fabric": + imageUrl = "/assets/img/fabric.png"; + break; + case "forge": + imageUrl = "/assets/img/forge.png"; + break; + case "liteloader": + imageUrl = "/assets/img/chicken.png"; + break; + case "optifine": + imageUrl = "/assets/img/command.png"; + break; + default: + imageUrl = null; break; - } } + } - if (!regularLibrary) { - String title = I18n.hasKey("install.installer." + libraryId) ? i18n("install.installer." + libraryId) : libraryId; - if (libraryVersion != null) { - TwoLineListItem item = new TwoLineListItem(); - item.setTitle(title); - item.setSubtitle(i18n("archive.version") + ": " + libraryVersion); - setCenter(item); - } else { - Label label = new Label(); - label.setStyle("-fx-font-size: 15px;"); - BorderPane.setAlignment(label, Pos.CENTER_LEFT); - setCenter(label); - } + public void setState(String libraryVersion, boolean incompatibleWithGame, boolean removable) { + this.libraryVersion.set(libraryVersion); + this.incompatibleWithGame.set(incompatibleWithGame); + this.removable.set(removable); + } + + public String getLibraryId() { + return id; + } + + @Override + protected Skin createDefaultSkin() { + return new InstallerItemSkin(this); + } + + public static class InstallerItemGroup { + public InstallerItem game = new InstallerItem(MINECRAFT); + public InstallerItem fabric = new InstallerItem(FABRIC); + public InstallerItem forge = new InstallerItem(FORGE); + public InstallerItem liteLoader = new InstallerItem(LITELOADER); + public InstallerItem optiFine = new InstallerItem(OPTIFINE); + + public InstallerItemGroup() { + forge.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> { + if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId(); + return null; + }, fabric.libraryVersion)); + + liteLoader.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> { + if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId(); + return null; + }, fabric.libraryVersion)); + + optiFine.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> { + if (fabric.libraryVersion.get() != null) return FABRIC.getPatchId(); + return null; + }, fabric.libraryVersion)); + + fabric.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> { + if (liteLoader.libraryVersion.get() != null) return LITELOADER.getPatchId(); + if (optiFine.libraryVersion.get() != null) return OPTIFINE.getPatchId(); + if (forge.libraryVersion.get() != null) return FORGE.getPatchId(); + return null; + }, optiFine.libraryVersion, forge.libraryVersion)); + } + + public InstallerItem[] getLibraries() { + return new InstallerItem[]{game, fabric, forge, liteLoader, optiFine}; } + } + + public static class InstallerItemSkin extends SkinBase { + + InstallerItemSkin(InstallerItem control) { + super(control); + + HBox hbox = new HBox(); + getChildren().setAll(hbox); + JFXDepthManager.setDepth(hbox, 1); - { - HBox hBox = new HBox(); + hbox.getStyleClass().add("card"); - if (upgrade != null) { - JFXButton upgradeButton = new JFXButton(); - if (libraryVersion == null) { - upgradeButton.setGraphic(SVG.arrowRight(Theme.blackFillBinding(), -1, -1)); + hbox.setAlignment(Pos.CENTER_LEFT); + + if (control.imageUrl != null) { + hbox.getChildren().add(FXUtils.limitingSize(new ImageView(new Image(control.imageUrl, 32, 32, true, true)), 32, 32)); + } + + Label nameLabel = new Label(); + hbox.getChildren().add(nameLabel); + nameLabel.setPrefWidth(80); + nameLabel.textProperty().set(I18n.hasKey("install.installer." + control.id) ? i18n("install.installer." + control.id) : control.id); + HBox.setMargin(nameLabel, new Insets(0, 4, 0, 4)); + + Label label = new Label(); + hbox.getChildren().add(label); + label.setMaxWidth(Double.MAX_VALUE); + HBox.setHgrow(label, Priority.ALWAYS); + label.textProperty().bind(Bindings.createStringBinding(() -> { + String incompatibleWith = control.incompatibleLibraryName.get(); + String version = control.libraryVersion.get(); + if (control.incompatibleWithGame.get()) { + return i18n("install.installer.change_version", version); + } else if (incompatibleWith != null) { + return i18n("install.installer.incompatible", i18n("install.installer." + incompatibleWith)); + } else if (version == null) { + return i18n("install.installer.not_installed"); } else { - upgradeButton.setGraphic(SVG.update(Theme.blackFillBinding(), -1, -1)); + return i18n("install.installer.version", version); } - upgradeButton.getStyleClass().add("toggle-icon4"); - FXUtils.installFastTooltip(upgradeButton, i18n("install.change_version")); - upgradeButton.setOnMouseClicked(e -> upgrade.run()); - hBox.getChildren().add(upgradeButton); - } + }, control.incompatibleLibraryName, control.incompatibleWithGame, control.libraryVersion)); + BorderPane.setMargin(label, new Insets(0, 0, 0, 8)); + BorderPane.setAlignment(label, Pos.CENTER_LEFT); - if (deleteCallback != null) { - JFXButton deleteButton = new JFXButton(); - deleteButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1)); - deleteButton.getStyleClass().add("toggle-icon4"); - deleteButton.setOnMouseClicked(e -> deleteCallback.accept(this)); - hBox.getChildren().add(deleteButton); - } + JFXButton closeButton = new JFXButton(); + closeButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1)); + closeButton.getStyleClass().add("toggle-icon4"); + closeButton.visibleProperty().bind(control.removable); + closeButton.managedProperty().bind(closeButton.visibleProperty()); + closeButton.onMouseClickedProperty().bind(control.removeAction); + hbox.getChildren().add(closeButton); + + JFXButton arrowButton = new JFXButton(); + arrowButton.graphicProperty().bind(Bindings.createObjectBinding(() -> control.upgradable.get() + ? SVG.update(Theme.blackFillBinding(), -1, -1) + : SVG.arrowRight(Theme.blackFillBinding(), -1, -1), + control.upgradable)); + arrowButton.getStyleClass().add("toggle-icon4"); + arrowButton.visibleProperty().bind(Bindings.createBooleanBinding( + () -> control.installable.get() && control.incompatibleLibraryName.get() == null, + control.installable, control.incompatibleLibraryName)); + arrowButton.managedProperty().bind(arrowButton.visibleProperty()); + arrowButton.onMouseClickedProperty().bind(control.action); + hbox.getChildren().add(arrowButton); - hBox.setAlignment(Pos.CENTER_RIGHT); - setRight(hBox); + FXUtils.onChangeAndOperate(arrowButton.visibleProperty(), clickable -> { + if (clickable) { + hbox.onMouseClickedProperty().bind(control.action); + hbox.setCursor(Cursor.HAND); + } else { + hbox.onMouseClickedProperty().unbind(); + hbox.onMouseClickedProperty().set(null); + hbox.setCursor(Cursor.DEFAULT); + } + }); } } - } 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 2799bc2856..c780ab917e 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 @@ -24,6 +24,7 @@ import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.util.Lang; @@ -53,10 +54,8 @@ public AdditionalInstallersPage(String gameVersion, Version version, WizardContr () -> compatible.get() && txtName.validate(), txtName.textProperty(), compatible)); - InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine}; - - for (InstallerPageItem library : libraries) { - String libraryId = library.id; + for (InstallerItem library : group.getLibraries()) { + String libraryId = library.getLibraryId(); if (libraryId.equals("game")) continue; library.removeAction.set(e -> { controller.getSettings().put(libraryId, new UpdateInstallerWizardProvider.RemoveVersionAction(libraryId)); @@ -90,28 +89,25 @@ protected void reload() { String liteLoader = analyzer.getVersion(LITELOADER).orElse(null); String optiFine = analyzer.getVersion(OPTIFINE).orElse(null); - InstallerPageItem[] libraries = new InstallerPageItem[]{this.game, this.fabric, this.forge, this.liteLoader, this.optiFine}; + InstallerItem[] libraries = group.getLibraries(); String[] versions = new String[]{game, fabric, forge, liteLoader, optiFine}; String currentGameVersion = Lang.nonNull(getVersion("game"), game); boolean compatible = true; for (int i = 0; i < libraries.length; ++i) { - String libraryId = libraries[i].id; + String libraryId = libraries[i].getLibraryId(); String libraryVersion = Lang.nonNull(getVersion(libraryId), versions[i]); boolean alreadyInstalled = versions[i] != null && !(controller.getSettings().get(libraryId) instanceof UpdateInstallerWizardProvider.RemoveVersionAction); if (!"game".equals(libraryId) && currentGameVersion != null && !currentGameVersion.equals(game) && getVersion(libraryId) == null && alreadyInstalled) { // For third-party libraries, if game version is being changed, and the library is not being reinstalled, // warns the user that we should update the library. - libraries[i].label.set(i18n("install.installer.change_version", i18n("install.installer." + libraryId), libraryVersion)); - libraries[i].removable.set(true); + libraries[i].setState(libraryVersion, /* incompatibleWithGame */ true, /* removable */ true); compatible = false; } else if (alreadyInstalled || getVersion(libraryId) != null) { - libraries[i].label.set(i18n("install.installer.version", i18n("install.installer." + libraryId), libraryVersion)); - libraries[i].removable.set(true); + libraries[i].setState(libraryVersion, /* incompatibleWithGame */ false, /* removable */ true); } else { - libraries[i].label.set(i18n("install.installer.not_installed", i18n("install.installer." + libraryId))); - libraries[i].removable.set(false); + libraries[i].setState(/* libraryVersion */ null, /* incompatibleWithGame */ false, /* removable */ false); } } this.compatible.set(compatible); 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 62b4fedb64..0dd7bfd6b3 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 @@ -19,29 +19,21 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXTextField; -import com.jfoenix.effects.JFXDepthManager; import javafx.beans.binding.Bindings; import javafx.beans.property.*; -import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.geometry.Insets; import javafx.geometry.Pos; -import javafx.scene.Cursor; import javafx.scene.control.Control; import javafx.scene.control.Label; import javafx.scene.control.Skin; import javafx.scene.control.SkinBase; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; -import org.jackhuang.hmcl.setting.Theme; -import org.jackhuang.hmcl.ui.FXUtils; -import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; @@ -55,11 +47,7 @@ public class InstallersPage extends Control implements WizardPage { protected final WizardController controller; - protected InstallerPageItem game = new InstallerPageItem("game"); - protected InstallerPageItem fabric = new InstallerPageItem("fabric"); - protected InstallerPageItem forge = new InstallerPageItem("forge"); - protected InstallerPageItem liteLoader = new InstallerPageItem("liteloader"); - protected InstallerPageItem optiFine = new InstallerPageItem("optifine"); + protected InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup(); protected JFXTextField txtName = new JFXTextField(); protected BooleanProperty installable = new SimpleBooleanProperty(); @@ -75,13 +63,15 @@ public InstallersPage(WizardController controller, GameRepository repository, St txtName.textProperty())); txtName.setText(gameVersion); - InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine}; + group.game.installable.setValue(false); - for (InstallerPageItem library : libraries) { - String libraryId = library.id; + for (InstallerItem library : group.getLibraries()) { + String libraryId = library.getLibraryId(); if (libraryId.equals("game")) continue; - library.action.set(e -> - controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false)))); + library.action.set(e -> { + if (library.incompatibleLibraryName.get() == null) + controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))); + }); library.removeAction.set(e -> { controller.getSettings().remove(libraryId); reload(); @@ -99,15 +89,13 @@ private String getVersion(String id) { } protected void reload() { - InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine}; - - for (InstallerPageItem library : libraries) { - String libraryId = library.id; + for (InstallerItem library : group.getLibraries()) { + String libraryId = library.getLibraryId(); if (controller.getSettings().containsKey(libraryId)) { - library.label.set(i18n("install.installer.version", i18n("install.installer." + libraryId), getVersion(libraryId))); + library.libraryVersion.set(getVersion(libraryId)); library.removable.set(true); } else { - library.label.setValue(i18n("install.installer.not_installed", i18n("install.installer." + libraryId))); + library.libraryVersion.set(null); library.removable.set(false); } } @@ -133,54 +121,8 @@ protected Skin createDefaultSkin() { return new InstallersPageSkin(this); } - protected static class InstallerPageItem { - String id; - StringProperty label = new SimpleStringProperty(); - BooleanProperty removable = new SimpleBooleanProperty(); - ObjectProperty> removeAction = new SimpleObjectProperty<>(); - ObjectProperty> action = new SimpleObjectProperty<>(); - - public InstallerPageItem(String id) { - this.id = id; - } - } - protected static class InstallersPageSkin extends SkinBase { - protected static class InstallersPageItemSkin extends BorderPane { - final ImageView imageView; - final Label label; - - InstallersPageItemSkin(String imageUrl, InstallerPageItem item, boolean clickable) { - getStyleClass().add("card"); - - setLeft(FXUtils.limitingSize(imageView = new ImageView(new Image(imageUrl, 32, 32, true, true)), 32, 32)); - setCenter(label = new Label()); - label.textProperty().bind(item.label); - BorderPane.setMargin(label, new Insets(0, 0, 0, 8)); - BorderPane.setAlignment(label, Pos.CENTER_LEFT); - - if (clickable) { - HBox right = new HBox(); - right.setAlignment(Pos.CENTER_RIGHT); - setRight(right); - JFXButton closeButton = new JFXButton(); - closeButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1)); - right.getChildren().add(closeButton); - closeButton.getStyleClass().add("toggle-icon4"); - closeButton.visibleProperty().bind(item.removable); - closeButton.onMouseClickedProperty().bind(item.removeAction); - onMouseClickedProperty().bind(item.action); - JFXButton arrowButton = new JFXButton(); - arrowButton.setGraphic(SVG.arrowRight(Theme.blackFillBinding(), -1, -1)); - arrowButton.onMouseClickedProperty().bind(item.action); - arrowButton.getStyleClass().add("toggle-icon4"); - right.getChildren().add(arrowButton); - setCursor(Cursor.HAND); - } - } - } - /** * Constructor for all SkinBase instances. * @@ -207,13 +149,7 @@ protected InstallersPageSkin(InstallersPage control) { list.getChildren().add(versionNamePane); } - InstallersPageItemSkin game = new InstallersPageItemSkin("/assets/img/grass.png", control.game, false); - InstallersPageItemSkin fabric = new InstallersPageItemSkin("/assets/img/fabric.png", control.fabric, true); - InstallersPageItemSkin forge = new InstallersPageItemSkin("/assets/img/forge.png", control.forge, true); - InstallersPageItemSkin liteLoader = new InstallersPageItemSkin("/assets/img/chicken.png", control.liteLoader, true); - InstallersPageItemSkin optiFine = new InstallersPageItemSkin("/assets/img/command.png", control.optiFine, true); - list.getChildren().addAll(game, fabric, forge, liteLoader, optiFine); - list.getChildren().forEach(node -> JFXDepthManager.setDepth(node, 1)); + list.getChildren().addAll(control.group.getLibraries()); { JFXButton installButton = new JFXButton(i18n("button.install")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index c2976bb737..4fe4249bb1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.versions; import javafx.application.Platform; +import javafx.beans.binding.Bindings; import javafx.scene.Node; import javafx.scene.control.Skin; import javafx.stage.FileChooser; @@ -42,6 +43,7 @@ import java.util.function.Consumer; import java.util.function.Function; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -74,7 +76,7 @@ public CompletableFuture loadVersion(Profile profile, String versionId) { return LibraryAnalyzer.analyze(profile.getRepository().getResolvedPreservingPatchesVersion(versionId)); }).thenAcceptAsync(analyzer -> { - Function> removeAction = libraryId -> x -> { + Function removeAction = libraryId -> () -> { profile.getDependency().removeLibraryAsync(version, libraryId) .thenComposeAsync(profile.getRepository()::saveAsync) .withComposeAsync(profile.getRepository().refreshVersionsAsync()) @@ -84,15 +86,28 @@ public CompletableFuture loadVersion(Profile profile, String versionId) { itemsProperty().clear(); - for (LibraryAnalyzer.LibraryType type : LibraryAnalyzer.LibraryType.values()) { - String libraryId = type.getPatchId(); - String libraryVersion = analyzer.getVersion(type).orElse(null); - Consumer action = "game".equals(libraryId) || libraryVersion == null ? null : removeAction.apply(libraryId); - itemsProperty().add(new InstallerItem(libraryId, libraryVersion, () -> { + InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup(); + + // Conventional libraries: game, fabric, forge, liteloader, optifine + for (InstallerItem installerItem : group.getLibraries()) { + String libraryId = installerItem.getLibraryId(); + String libraryVersion = analyzer.getVersion(libraryId).orElse(null); + installerItem.libraryVersion.set(libraryVersion); + installerItem.upgradable.set(libraryVersion != null); + installerItem.installable.set(true); + installerItem.action.set(e -> { Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); - }, action)); + }); + boolean removable = !"game".equals(libraryId) && libraryVersion != null; + installerItem.removable.set(removable); + if (removable) { + Runnable action = removeAction.apply(libraryId); + installerItem.removeAction.set(e -> action.run()); + } + itemsProperty().add(installerItem); } + // other third-party libraries which are unable to manage. for (LibraryAnalyzer.LibraryMark mark : analyzer) { String libraryId = mark.getLibraryId(); String libraryVersion = mark.getLibraryVersion(); @@ -101,14 +116,23 @@ public CompletableFuture loadVersion(Profile profile, String versionId) { if (LibraryAnalyzer.LibraryType.fromPatchId(libraryId) != null) continue; - Consumer action = removeAction.apply(libraryId); - if (libraryVersion != null && Lang.test(() -> profile.getDependency().getVersionList(libraryId))) - itemsProperty().add( - new InstallerItem(libraryId, libraryVersion, () -> { - Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); - }, action)); - else - itemsProperty().add(new InstallerItem(libraryId, libraryVersion, null, action)); + Runnable action = removeAction.apply(libraryId); + + InstallerItem installerItem = new InstallerItem(libraryId); + installerItem.libraryVersion.set(libraryVersion); + installerItem.installable.set(false); + installerItem.upgradable.bind(installerItem.installable); + installerItem.removable.set(true); + installerItem.removeAction.set(e -> action.run()); + + if (libraryVersion != null && Lang.test(() -> profile.getDependency().getVersionList(libraryId))) { + installerItem.installable.set(true); + installerItem.action.set(e -> { + Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); + }); + } + + itemsProperty().add(installerItem); } }, Platform::runLater); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 706e0ba9e4..0b478dfb87 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -139,11 +139,12 @@ install.failed.install_online=Unable to recognize the provided installer file install.failed.malformed=The files just downloaded a moment ago is malformed. You may switch to other download provider to resolve this problem. install.failed.optifine_conflict=Fabric, OptiFine and Forge are installed simultaneously on Minecraft 1.13 install.failed.version_mismatch=The library requires the game version %s, but the actual version is %s. -install.installer.change_version=%s version: %s, this version is not compatible with current game version. Click here to choose another one. +install.installer.change_version=%s, this version is not compatible with current game version. Click here to choose another one. install.installer.choose=Choose a %s version install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft +install.installer.incompatible=Incompatible with %s install.installer.install=Install %s install.installer.install_offline=Install/Upgrade from file install.installer.install_offline.extension=Forge/OptiFine installer @@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=Supports import of Forge/OptiFine inst install.installer.install_online=Install Online install.installer.install_online.tooltip=Support installation of Fabric, Forge, OptiFine, LiteLoader. install.installer.liteloader=LiteLoader -install.installer.not_installed=%s Version: not installed +install.installer.not_installed=Not installed install.installer.optifine=OptiFine -install.installer.version=%s Version: %s +install.installer.version=%s install.modpack=Install a modpack install.new_game=Install a New Game install.new_game.already_exists=This version already exists. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 7e6452fe16..95bcd5841c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -140,6 +140,7 @@ install.installer.choose=Escoja una versión de %s install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft +install.installer.incompatible=Incompatible with %s install.installer.install=Instalar %s install.installer.install_offline=Instalar/actualizar con archivo local install.installer.install_offline.extension=Instalador de Forge/OptiFine @@ -147,9 +148,9 @@ install.installer.install_offline.tooltip=Soporta importación de archivo instal install.installer.install_online=Instalar en línea install.installer.install_online.tooltip=Soporta instalación de Fabric, Forge, OptiFine, LiteLoader install.installer.liteloader=LiteLoader -install.installer.not_installed=%s no está instalado +install.installer.not_installed=no está instalado install.installer.optifine=OptiFine -install.installer.version=Versión %s: %s +install.installer.version=%s install.modpack=Instalar un modpack install.new_game=Instalar un juego nuevo install.new_game.already_exists=Esta versión ya existe. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 122945d361..a60483b569 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -139,11 +139,12 @@ install.failed.install_online=Невозможно распознать пред install.failed.malformed=Файлы, скачаные минуту назад, неправильно сформированы. Для решения этой проблемы можно переключиться на другого поставщика скачивания. install.failed.optifine_conflict=Fabric, OptiFine и Forge установлены одновременно на Minecraft 1.13 install.failed.version_mismatch=Библиотека требует версию игры %s, но фактическая версия %s. -install.installer.change_version=Версия %s: %s, эта версия не совместима с текущей версией игры. Что бы выбрать другую, нажмите здесь. +install.installer.change_version=%s, эта версия не совместима с текущей версией игры. Что бы выбрать другую, нажмите здесь. install.installer.choose=Выберите версию %s install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft +install.installer.incompatible=Incompatible with %s install.installer.install=Установка %s install.installer.install_offline=Установить/обновить из файла install.installer.install_offline.extension=Установщик Forge/OptiFine @@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=Поддерживает импорт install.installer.install_online=Установить из сети install.installer.install_online.tooltip=Поддерживается установка Fabric, Forge, OptiFine, LiteLoader. install.installer.liteloader=LiteLoader -install.installer.not_installed=%s не установлен +install.installer.not_installed=не установлен install.installer.optifine=OptiFine -install.installer.version=%s - версия: %s +install.installer.version=%s install.modpack=Установить модпак install.new_game=Установка новой игры install.new_game.already_exists=Эта версия уже существует. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 034b1f0a30..2eaa6113e3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -139,11 +139,12 @@ install.failed.install_online=無法識別要安裝的軟體 install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到其他下載來源以解決此問題。 install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上 install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。 -install.installer.change_version=%s 版本: %s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除 +install.installer.change_version=%s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除 install.installer.choose=選擇 %s 版本 install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft +install.installer.incompatible=與 %s 不相容 install.installer.install=安裝%s install.installer.install_offline=從本機檔案安裝或升級 install.installer.install_offline.extension=Forge/OptiFine 安裝器 @@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=支援匯入已經下載好的 Forge/O install.installer.install_online=線上安裝 install.installer.install_online.tooltip=支援安裝 Fabric、Forge、OptiFine、LiteLoader install.installer.liteloader=LiteLoader -install.installer.not_installed=%s 版本: 不安裝 +install.installer.not_installed=不安裝 install.installer.optifine=OptiFine -install.installer.version=%s 版本: %s +install.installer.version=%s install.modpack=安裝整合包 install.new_game=安裝新遊戲版本 install.new_game.already_exists=此版本已經存在,請重新命名 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 f33e891f1b..c9d17e02a3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -139,11 +139,12 @@ install.failed.install_online=无法识别要安装的软件 install.failed.malformed=刚才下载的文件格式损坏。您可以切换到其他下载源来解决此问题。 install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 与 Forge 同时安装在 Minecraft 1.13 及以上版本 install.failed.version_mismatch=该软件需要的游戏版本为 %s,但实际的游戏版本为 %s。 -install.installer.change_version=%s 版本: %s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除 +install.installer.change_version=%s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除 install.installer.choose=选择 %s 版本 install.installer.fabric=Fabric install.installer.forge=Forge install.installer.game=Minecraft +install.installer.incompatible=与 %s 不兼容 install.installer.install=安装 %s install.installer.install_offline=从本地文件安装/升级 install.installer.install_offline.extension=Forge/OptiFine 安装器 @@ -151,9 +152,9 @@ install.installer.install_offline.tooltip=支持导入已经下载好的 Forge/O install.installer.install_online=在线安装 install.installer.install_online.tooltip=支持安装 Fabric、Forge、OptiFine、LiteLoader install.installer.liteloader=LiteLoader -install.installer.not_installed=%s 版本: 不安装 +install.installer.not_installed=不安装 install.installer.optifine=OptiFine -install.installer.version=%s 版本: %s +install.installer.version=%s install.modpack=安装整合包 install.new_game=安装新游戏版本 install.new_game.already_exists=此版本已经存在,请换一个名字 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 943dd7e836..dcb18ec26c 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 @@ -104,7 +104,7 @@ public Collection> getDependencies() { public void execute() throws IOException, VersionMismatchException, OptiFineInstallTask.UnsupportedOptiFineInstallationException { String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0) { - // Forge 1.13 is not compatible with any other libraries. + // Forge 1.13 is not compatible with fabric. if (!LibraryAnalyzer.VANILLA_MAIN.equals(originalMainClass) && !LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(originalMainClass) && !LibraryAnalyzer.LAUNCH_WRAPPER_MAIN.equals(originalMainClass)) throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException(); } else { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6713fe9cd9..42a37a618d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip From 476c41b29b29b7bc20930cc0bcd3fe32cff8df5f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 6 May 2020 17:37:55 +0800 Subject: [PATCH 0382/2639] fix: sometimes cannot edit modpack versiojn settings --- .../java/org/jackhuang/hmcl/game/HMCLGameRepository.java | 5 +++++ 1 file changed, 5 insertions(+) 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 a6181ddbf7..c7e70fa56f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -81,6 +81,11 @@ protected void refreshVersionsImpl() { localVersionSettings.clear(); super.refreshVersionsImpl(); versions.keySet().forEach(this::loadLocalVersionSetting); + versions.keySet().forEach(version -> { + if (isModpack(version)) { + specializeVersionSetting(version); + } + }); try { File file = new File(getBaseDirectory(), "launcher_profiles.json"); From bfb55a38135b10601afc9d884dec8a18f2ec1bd9 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 28 May 2020 23:16:56 +0800 Subject: [PATCH 0383/2639] add: upload skin --- .../main/java/org/jackhuang/hmcl/ui/SVG.java | 4 ++ .../hmcl/ui/account/AccountListItem.java | 41 +++++++++++++- .../hmcl/ui/account/AccountListItemSkin.java | 10 ++++ .../hmcl/ui/construct/MultiFileItem.java | 1 + .../hmcl/ui/construct/PromptDialogPane.java | 26 +++++++++ .../resources/assets/lang/I18N.properties | 5 ++ .../resources/assets/lang/I18N_zh.properties | 5 ++ .../assets/lang/I18N_zh_CN.properties | 5 ++ .../AuthlibInjectorProvider.java | 5 ++ .../yggdrasil/MojangYggdrasilProvider.java | 7 ++- .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 17 +++--- .../auth/yggdrasil/YggdrasilProvider.java | 18 ++++++ .../hmcl/auth/yggdrasil/YggdrasilService.java | 22 ++++++++ .../hmcl/util/io/HttpMultipartRequest.java | 56 +++++++++++++++++++ 14 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 77fad10555..bd4019560b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -186,4 +186,8 @@ public static Node arrowRight(ObjectBinding fill, double width, public static Node wrench(ObjectBinding fill, double width, double height) { return createSVGPath("M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z", fill, width, height); } + + public static Node upload(ObjectBinding fill, double width, double height) { + return createSVGPath("M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z", fill, width, height); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java index 3f1d450a9b..8bb0732496 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java @@ -23,23 +23,28 @@ import javafx.scene.control.RadioButton; import javafx.scene.control.Skin; import javafx.scene.image.Image; +import javafx.stage.FileChooser; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.CredentialExpiredException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.offline.OfflineAccount; +import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.TexturesLoader; import org.jackhuang.hmcl.setting.Accounts; +import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; +import org.jackhuang.hmcl.ui.construct.PromptDialogPane; + +import java.io.File; +import java.util.concurrent.CancellationException; +import java.util.logging.Level; import static org.jackhuang.hmcl.util.Lang.thread; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -import java.util.concurrent.CancellationException; -import java.util.logging.Level; - public class AccountListItem extends RadioButton { private final Account account; @@ -96,6 +101,36 @@ public void refresh() { }); } + public boolean canUploadSkin() { + return account instanceof YggdrasilAccount && !(account instanceof AuthlibInjectorAccount); + } + + public void uploadSkin() { + if (!(account instanceof YggdrasilAccount)) { + return; + } + + FileChooser chooser = new FileChooser(); + chooser.setTitle(i18n("account.skin.upload")); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("account.skin.file"), "*.png")); + File selectedFile = chooser.showOpenDialog(Controllers.getStage()); + if (selectedFile == null) { + return; + } + + Controllers.prompt(new PromptDialogPane.Builder(i18n("account.skin.upload"), (questions, resolve, reject) -> { + PromptDialogPane.Builder.CandidatesQuestion q = (PromptDialogPane.Builder.CandidatesQuestion) questions.get(0); + String model = q.getValue() == 0 ? "" : "slim"; + try { + ((YggdrasilAccount) account).uploadSkin(model, selectedFile.toPath()); + resolve.run(); + } catch (AuthenticationException e) { + reject.accept(AddAccountPane.accountException(e)); + } + }).addQuestion(new PromptDialogPane.Builder.CandidatesQuestion(i18n("account.skin.model"), + i18n("account.skin.model.default"), i18n("account.skin.model.slim")))); + } + public void remove() { Accounts.getAccounts().remove(account); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 6da83205f5..5230e51236 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -84,6 +84,7 @@ public void fire() { HBox right = new HBox(); right.setAlignment(Pos.CENTER_RIGHT); + JFXButton btnRefresh = new JFXButton(); btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); btnRefresh.getStyleClass().add("toggle-icon4"); @@ -91,6 +92,15 @@ public void fire() { runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh"))); right.getChildren().add(btnRefresh); + if (skinnable.canUploadSkin()) { + JFXButton btnUpload = new JFXButton(); + btnUpload.setOnMouseClicked(e -> skinnable.uploadSkin()); + btnUpload.getStyleClass().add("toggle-icon4"); + btnUpload.setGraphic(SVG.upload(Theme.blackFillBinding(), -1, -1)); + runInFX(() -> FXUtils.installFastTooltip(btnUpload, i18n("account.skin.upload"))); + right.getChildren().add(btnUpload); + } + JFXButton btnRemove = new JFXButton(); btnRemove.setOnMouseClicked(e -> skinnable.remove()); btnRemove.getStyleClass().add("toggle-icon4"); 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 dcf35b252e..076206251f 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 @@ -148,6 +148,7 @@ public Node createChildren(String title, String subtitle, T userData) { pane.setLeft(left); Label right = new Label(subtitle); + right.setWrapText(true); right.getStyleClass().add("subtitle-label"); right.setStyle("-fx-font-size: 10;"); pane.setRight(right); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PromptDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PromptDialogPane.java index 7d1512d581..abc3ba8585 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PromptDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/PromptDialogPane.java @@ -19,6 +19,7 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXCheckBox; +import com.jfoenix.controls.JFXComboBox; import com.jfoenix.controls.JFXTextField; import com.jfoenix.validation.base.ValidatorBase; import javafx.beans.binding.Bindings; @@ -81,6 +82,18 @@ public PromptDialogPane(Builder builder) { checkBox.selectedProperty().addListener((a, b, newValue) -> ((Builder.BooleanQuestion) question).value = newValue); checkBox.setText(question.question); vbox.getChildren().add(hBox); + } else if (question instanceof Builder.CandidatesQuestion) { + HBox hBox = new HBox(); + JFXComboBox comboBox = new JFXComboBox<>(); + hBox.getChildren().setAll(comboBox); + comboBox.getItems().setAll(((Builder.CandidatesQuestion) question).candidates); + comboBox.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> + ((Builder.CandidatesQuestion) question).value = newValue.intValue()); + comboBox.getSelectionModel().select(0); + if (StringUtils.isNotBlank(question.question)) { + vbox.getChildren().add(new Label(question.question)); + } + vbox.getChildren().add(hBox); } } @@ -146,6 +159,19 @@ public StringQuestion(String question, String defaultValue, ValidatorBase... val } } + public static class CandidatesQuestion extends Question { + protected final List candidates; + + public CandidatesQuestion(String question, String... candidates) { + super(question); + this.value = null; + if (candidates == null || candidates.length == 0) { + throw new IllegalArgumentException("At least one candidate required"); + } + this.candidates = new ArrayList<>(Arrays.asList(candidates)); + } + } + public static class BooleanQuestion extends Question { public BooleanQuestion(String question, boolean defaultValue) { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 0b478dfb87..b03b9d6abb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -62,6 +62,11 @@ account.methods.yggdrasil=Mojang account.missing=No Account account.missing.add=Click here to add account.password=Password +account.skin.file=Skin file +account.skin.model=Character model +account.skin.model.default=Steve +account.skin.model.slim=Alex +account.skin.upload=Upload skin account.username=Name archive.author=Authors diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 2eaa6113e3..5a61315000 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -62,6 +62,11 @@ account.methods.yggdrasil=正版登入 account.missing=沒有遊戲帳戶 account.missing.add=按一下此處加入帳戶 account.password=密碼 +account.skin.file=皮膚圖片檔案 +account.skin.model=人物模型 +account.skin.model.default=Steve +account.skin.model.slim=Alex +account.skin.upload=上傳皮膚 account.username=使用者名稱 archive.author=作者 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 c9d17e02a3..fbcf6f54f3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -62,6 +62,11 @@ account.methods.yggdrasil=正版登录 account.missing=没有游戏账户 account.missing.add=点击此处添加账户 account.password=密码 +account.skin.file=皮肤图片文件 +account.skin.model=人物模型 +account.skin.model.default=Steve +account.skin.model.slim=Alex +account.skin.upload=上传皮肤 account.username=用户名 archive.author=作者 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorProvider.java index 9f876e98eb..6fcb53c096 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorProvider.java @@ -53,6 +53,11 @@ public URL getInvalidationURL() throws AuthenticationException { return toURL(apiRoot + "authserver/invalidate"); } + @Override + public URL getSkinUploadURL(UUID uuid) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + @Override public URL getProfilePropertiesURL(UUID uuid) throws AuthenticationException { return toURL(apiRoot + "sessionserver/session/minecraft/profile/" + UUIDTypeAdapter.fromUUID(uuid)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/MojangYggdrasilProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/MojangYggdrasilProvider.java index 0c514b0d58..ea6237ad33 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/MojangYggdrasilProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/MojangYggdrasilProvider.java @@ -21,7 +21,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import java.net.URL; -import java.util.UUID; +import java.util.*; public class MojangYggdrasilProvider implements YggdrasilProvider { @@ -45,6 +45,11 @@ public URL getInvalidationURL() { return NetworkUtils.toURL("https://authserver.mojang.com/invalidate"); } + @Override + public URL getSkinUploadURL(UUID uuid) throws UnsupportedOperationException { + return NetworkUtils.toURL("https://api.mojang.com/user/profile/" + UUIDTypeAdapter.fromUUID(uuid) + "/skin"); + } + @Override public URL getProfilePropertiesURL(UUID uuid) { return NetworkUtils.toURL("https://sessionserver.mojang.com/session/minecraft/profile/" + UUIDTypeAdapter.fromUUID(uuid)); 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 377e789965..8200b52d00 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,13 +17,7 @@ */ package org.jackhuang.hmcl.auth.yggdrasil; -import static java.util.Objects.requireNonNull; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - +import javafx.beans.binding.ObjectBinding; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthenticationException; @@ -34,7 +28,10 @@ import org.jackhuang.hmcl.auth.ServerResponseMalformedException; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; -import javafx.beans.binding.ObjectBinding; +import java.nio.file.Path; +import java.util.*; + +import static java.util.Objects.requireNonNull; public class YggdrasilAccount extends Account { @@ -193,6 +190,10 @@ public void clearCache() { service.getProfileRepository().invalidate(characterUUID); } + public void uploadSkin(String model, Path file) throws AuthenticationException, UnsupportedOperationException { + service.uploadSkin(characterUUID, model, file); + } + private static String randomClientToken() { return UUIDTypeAdapter.fromUUID(UUID.randomUUID()); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilProvider.java index 35b2b02a4d..00c8f66816 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilProvider.java @@ -35,6 +35,24 @@ public interface YggdrasilProvider { URL getInvalidationURL() throws AuthenticationException; + /** + * URL to upload skin. + * + * Headers: + * Authentication: Bearer <access token> + * + * Payload: + * The payload for this API consists of multipart form data. There are two parts (order does not matter b/c of boundary): + * model: Empty string for the default model and "slim" for the slim model + * file: Raw image file data + * + * @see https://wiki.vg/Mojang_API#Upload_Skin + * @return url to upload skin + * @throws AuthenticationException if url cannot be generated. e.g. some parameter or query is malformed. + * @throws UnsupportedOperationException if the Yggdrasil provider does not support third-party skin uploading. + */ + URL getSkinUploadURL(UUID uuid) throws AuthenticationException, UnsupportedOperationException; + URL getProfilePropertiesURL(UUID uuid) throws AuthenticationException; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java index 2973c0c6db..3eebb77c1a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java @@ -26,11 +26,17 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; import org.jackhuang.hmcl.util.gson.ValidationTypeAdapterFactory; +import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.io.HttpMultipartRequest; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.javafx.ObservableOptionalCache; import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -145,6 +151,22 @@ public void invalidate(String accessToken, String clientToken) throws Authentica requireEmpty(request(provider.getInvalidationURL(), createRequestWithCredentials(accessToken, clientToken))); } + public void uploadSkin(UUID uuid, String model, Path file) throws AuthenticationException, UnsupportedOperationException { + try { + HttpURLConnection con = NetworkUtils.createHttpConnection(provider.getSkinUploadURL(uuid)); + con.setRequestMethod("PUT"); + con.setDoOutput(true); + try (HttpMultipartRequest request = new HttpMultipartRequest(con)) { + try (InputStream fis = Files.newInputStream(file)) { + request.file("file", FileUtils.getName(file), "image/" + FileUtils.getExtension(file), fis); + } + request.param("model", model); + } + } catch (IOException e) { + throw new AuthenticationException(e); + } + } + /** * Get complete game profile. * diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java new file mode 100644 index 0000000000..dfc03ac6f7 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java @@ -0,0 +1,56 @@ +package org.jackhuang.hmcl.util.io; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class HttpMultipartRequest implements Closeable { + private final String boundary = "*****" + System.currentTimeMillis() + "*****"; + private final HttpURLConnection urlConnection; + private final ByteArrayOutputStream stream; + private final String endl = "\r\n"; + + public HttpMultipartRequest(HttpURLConnection urlConnection) throws IOException { + this.urlConnection = urlConnection; + urlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); + + stream = new ByteArrayOutputStream(); + } + + private void addLine(String content) throws IOException { + stream.write(content.getBytes(UTF_8)); + stream.write(endl.getBytes(UTF_8)); + } + + public HttpMultipartRequest file(String name, String filename, String contentType, InputStream inputStream) throws IOException { + addLine("--" + boundary); + addLine(String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", name, filename)); + addLine("Content-Type: " + contentType); + addLine("Content-Transfer-Encoding: binary"); + addLine(""); + IOUtils.copyTo(inputStream, stream); + return this; + } + + public HttpMultipartRequest param(String name, String value) throws IOException { + addLine("--" + boundary); + addLine(String.format("Content-Disposition: form-data; name=\"%s\"", name)); + addLine(""); + addLine(value); + return this; + } + + @Override + public void close() throws IOException { + addLine("--" + boundary + "--"); + urlConnection.setRequestProperty("Content-Length", "" + stream.size()); + try (OutputStream os = urlConnection.getOutputStream()) { + IOUtils.write(stream.toByteArray(), os); + } + } +} From 5805914ebb71cfca18e83d200828e7b872482d8f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 1 Jun 2020 11:59:21 +0800 Subject: [PATCH 0384/2639] fix: upload skin --- .../hmcl/ui/account/AccountListItem.java | 29 +++++++++++++------ .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 2 +- .../hmcl/auth/yggdrasil/YggdrasilService.java | 10 +++++-- .../hmcl/util/io/HttpMultipartRequest.java | 21 +++++++++++++- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java index 8bb0732496..8917c27a6d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java @@ -33,6 +33,8 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.TexturesLoader; import org.jackhuang.hmcl.setting.Accounts; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; import org.jackhuang.hmcl.ui.construct.PromptDialogPane; @@ -82,9 +84,9 @@ protected Skin createDefaultSkin() { return new AccountListItemSkin(this); } - public void refresh() { - account.clearCache(); - thread(() -> { + private Task refreshAsync() { + return Task.runAsync(() -> { + account.clearCache(); try { account.logIn(); } catch (CredentialExpiredException e) { @@ -94,13 +96,19 @@ public void refresh() { // ignore cancellation } catch (Exception e1) { LOG.log(Level.WARNING, "Failed to refresh " + account + " with password", e1); + throw e1; } } catch (AuthenticationException e) { LOG.log(Level.WARNING, "Failed to refresh " + account + " with token", e); + throw e; } }); } + public void refresh() { + refreshAsync().whenComplete(e -> {}).start(); + } + public boolean canUploadSkin() { return account instanceof YggdrasilAccount && !(account instanceof AuthlibInjectorAccount); } @@ -121,12 +129,15 @@ public void uploadSkin() { Controllers.prompt(new PromptDialogPane.Builder(i18n("account.skin.upload"), (questions, resolve, reject) -> { PromptDialogPane.Builder.CandidatesQuestion q = (PromptDialogPane.Builder.CandidatesQuestion) questions.get(0); String model = q.getValue() == 0 ? "" : "slim"; - try { - ((YggdrasilAccount) account).uploadSkin(model, selectedFile.toPath()); - resolve.run(); - } catch (AuthenticationException e) { - reject.accept(AddAccountPane.accountException(e)); - } + refreshAsync() + .thenRunAsync(() -> ((YggdrasilAccount) account).uploadSkin(model, selectedFile.toPath())) + .thenComposeAsync(this::refreshAsync) + .thenRunAsync(Schedulers.javafx(), resolve::run) + .whenComplete(Schedulers.javafx(), e -> { + if (e != null) { + reject.accept(AddAccountPane.accountException(e)); + } + }).start(); }).addQuestion(new PromptDialogPane.Builder.CandidatesQuestion(i18n("account.skin.model"), i18n("account.skin.model.default"), i18n("account.skin.model.slim")))); } 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 8200b52d00..dbc13a9372 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 @@ -191,7 +191,7 @@ public void clearCache() { } public void uploadSkin(String model, Path file) throws AuthenticationException, UnsupportedOperationException { - service.uploadSkin(characterUUID, model, file); + service.uploadSkin(characterUUID, session.getAccessToken(), model, file); } private static String randomClientToken() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java index 3eebb77c1a..ed8dd1f018 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.util.gson.ValidationTypeAdapterFactory; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.HttpMultipartRequest; +import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.javafx.ObservableOptionalCache; @@ -151,16 +152,21 @@ public void invalidate(String accessToken, String clientToken) throws Authentica requireEmpty(request(provider.getInvalidationURL(), createRequestWithCredentials(accessToken, clientToken))); } - public void uploadSkin(UUID uuid, String model, Path file) throws AuthenticationException, UnsupportedOperationException { + public void uploadSkin(UUID uuid, String accessToken, String model, Path file) throws AuthenticationException, UnsupportedOperationException { try { HttpURLConnection con = NetworkUtils.createHttpConnection(provider.getSkinUploadURL(uuid)); con.setRequestMethod("PUT"); + con.setRequestProperty("Authorization", "Bearer " + accessToken); con.setDoOutput(true); try (HttpMultipartRequest request = new HttpMultipartRequest(con)) { + request.param("model", model); try (InputStream fis = Files.newInputStream(file)) { request.file("file", FileUtils.getName(file), "image/" + FileUtils.getExtension(file), fis); } - request.param("model", model); + } + String response = IOUtils.readFullyAsString(con.getInputStream()); + if (response.startsWith("{")) { + handleErrorMessage(fromJson(response, ErrorResponse.class)); } } catch (IOException e) { throw new AuthenticationException(e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java index dfc03ac6f7..19f24c0a68 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpMultipartRequest.java @@ -1,3 +1,20 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui and contributors + * + * 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 . + */ package org.jackhuang.hmcl.util.io; import java.io.ByteArrayOutputStream; @@ -17,6 +34,8 @@ public class HttpMultipartRequest implements Closeable { public HttpMultipartRequest(HttpURLConnection urlConnection) throws IOException { this.urlConnection = urlConnection; + urlConnection.setDoOutput(true); + urlConnection.setUseCaches(false); urlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); stream = new ByteArrayOutputStream(); @@ -31,9 +50,9 @@ public HttpMultipartRequest file(String name, String filename, String contentTyp addLine("--" + boundary); addLine(String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", name, filename)); addLine("Content-Type: " + contentType); - addLine("Content-Transfer-Encoding: binary"); addLine(""); IOUtils.copyTo(inputStream, stream); + addLine(""); return this; } From 0984c232537770cf3e521bdd29f94d77dc97af10 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 1 Jun 2020 13:05:55 +0800 Subject: [PATCH 0385/2639] alt: skin icon --- HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java | 4 ++++ .../org/jackhuang/hmcl/ui/account/AccountListItemSkin.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index bd4019560b..7af072c832 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -190,4 +190,8 @@ public static Node wrench(ObjectBinding fill, double width, dou public static Node upload(ObjectBinding fill, double width, double height) { return createSVGPath("M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z", fill, width, height); } + + public static Node hanger(ObjectBinding fill, double width, double height) { + return createSVGPath("M12 4A3.5 3.5 0 0 0 8.5 7.5H10.5A1.5 1.5 0 0 1 12 6A1.5 1.5 0 0 1 13.5 7.5A1.5 1.5 0 0 1 12 9C11.45 9 11 9.45 11 10V11.75L2.4 18.2A1 1 0 0 0 3 20H21A1 1 0 0 0 21.6 18.2L13 11.75V10.85A3.5 3.5 0 0 0 15.5 7.5A3.5 3.5 0 0 0 12 4M12 13.5L18 18H6Z", fill, width, height); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 5230e51236..d56a670a99 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -96,7 +96,7 @@ public void fire() { JFXButton btnUpload = new JFXButton(); btnUpload.setOnMouseClicked(e -> skinnable.uploadSkin()); btnUpload.getStyleClass().add("toggle-icon4"); - btnUpload.setGraphic(SVG.upload(Theme.blackFillBinding(), -1, -1)); + btnUpload.setGraphic(SVG.hanger(Theme.blackFillBinding(), -1, -1)); runInFX(() -> FXUtils.installFastTooltip(btnUpload, i18n("account.skin.upload"))); right.getChildren().add(btnUpload); } From 6eb0c16fcc77a7177af8ace0e5064f10ba2a139e Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 1 Jun 2020 13:26:28 +0800 Subject: [PATCH 0386/2639] fix: retry url in LibraryDownloadTask --- .../download/game/LibraryDownloadTask.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) 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 8447e9b9c6..e202f2d8c2 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 @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -42,6 +41,7 @@ import static org.jackhuang.hmcl.util.DigestUtils.digest; import static org.jackhuang.hmcl.util.Hex.encodeHex; +import static org.jackhuang.hmcl.util.Logging.LOG; public class LibraryDownloadTask extends Task { private FileDownloadTask task; @@ -111,7 +111,7 @@ public boolean doPreExecute() { } @Override - public void preExecute() throws Exception { + public void preExecute() { Optional libPath = cacheRepository.getLibrary(originalLibrary); if (libPath.isPresent()) { try { @@ -119,32 +119,42 @@ public void preExecute() throws Exception { cached = true; return; } catch (IOException e) { - Logging.LOG.log(Level.WARNING, "Failed to copy file from cache", e); + LOG.log(Level.WARNING, "Failed to copy file from cache", e); // We cannot copy cached file to current location // so we try to download a new one. } } - try { - URL packXz = NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(url) + ".pack.xz"); - if (NetworkUtils.urlExists(packXz)) { - List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz"); - task = new FileDownloadTask(urls, xzFile, null); - task.setCacheRepository(cacheRepository); - task.setCaching(true); - xz = true; - } else { - List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url); - task = new FileDownloadTask(urls, jar, - library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null); - task.setCacheRepository(cacheRepository); - task.setCaching(true); - task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); - xz = false; + if (testURLExistence(url)) { + List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz"); + task = new FileDownloadTask(urls, xzFile, null); + task.setCacheRepository(cacheRepository); + task.setCaching(true); + xz = true; + } else { + List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url); + task = new FileDownloadTask(urls, jar, + library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null); + task.setCacheRepository(cacheRepository); + task.setCaching(true); + task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); + xz = false; + } + } + + private boolean testURLExistence(String rawUrl) { + List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(rawUrl); + for (URL url : urls) { + URL xzURL = NetworkUtils.toURL(url.toString() + ".pack.xz"); + for (int retry = 0; retry < 3; retry++) { + try { + return NetworkUtils.urlExists(xzURL); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to test for url existence: " + rawUrl + ".pack.xz", e); + } } - } catch (IOException e) { - throw new LibraryDownloadException(library, e); } + return false; // maybe some ugly implementation will give timeout for not existent url. } @Override @@ -201,11 +211,11 @@ private static boolean validateJar(byte[] data, List checksums) throws I String target = hash.substring(validChecksum.length() + 1); String checksum = files.get(target); if ((!files.containsKey(target)) || (checksum == null)) { - Logging.LOG.warning(" " + target + " : missing"); + LOG.warning(" " + target + " : missing"); failed = true; break; } else if (!checksum.equals(validChecksum)) { - Logging.LOG.warning(" " + target + " : failed (" + checksum + ", " + validChecksum + ")"); + LOG.warning(" " + target + " : failed (" + checksum + ", " + validChecksum + ")"); failed = true; break; } From 53ff657106fc475093118d82c6e72ffa520ce2dc Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 1 Jun 2020 16:58:06 +0800 Subject: [PATCH 0387/2639] fix: #722 --- .../java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java | 1 - 1 file changed, 1 deletion(-) 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 52d452cb26..27000be175 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 @@ -38,7 +38,6 @@ public enum MessageType { WARNING, QUESTION, FINE, - PLAIN, } @FXML From 64d9fa7c6b37596f262768473f5657a426a15d22 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 14 Jun 2020 19:51:46 +0800 Subject: [PATCH 0388/2639] fix: #729 --- .../java/org/jackhuang/hmcl/upgrade/RemoteVersion.java | 3 ++- .../jackhuang/hmcl/download/game/LibraryDownloadTask.java | 3 ++- .../org/jackhuang/hmcl/util/platform/SystemUtils.java | 4 ++++ README.md | 8 ++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java index 6a7c0df665..82142b8ef9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jackhuang.hmcl.util.platform.SystemUtils; import java.io.IOException; import java.util.Optional; @@ -37,7 +38,7 @@ public static RemoteVersion fetch(String url) throws IOException { String jarHash = Optional.ofNullable(response.get("jarsha1")).map(JsonElement::getAsString).orElse(null); String packXZUrl = Optional.ofNullable(response.get("packxz")).map(JsonElement::getAsString).orElse(null); String packXZHash = Optional.ofNullable(response.get("packxzsha1")).map(JsonElement::getAsString).orElse(null); - if (packXZUrl != null && packXZHash != null) { + if (SystemUtils.JRE_CAPABILITY_PACK200 && packXZUrl != null && packXZHash != null) { return new RemoteVersion(version, packXZUrl, Type.PACK_XZ, new IntegrityCheck("SHA-1", packXZHash)); } else if (jarUrl != null && jarHash != null) { return new RemoteVersion(version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash)); 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 e202f2d8c2..871d17942b 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 @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jackhuang.hmcl.util.platform.SystemUtils; import org.tukaani.xz.XZInputStream; import java.io.*; @@ -125,7 +126,7 @@ public void preExecute() { } } - if (testURLExistence(url)) { + if (SystemUtils.JRE_CAPABILITY_PACK200 && testURLExistence(url)) { List urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz"); task = new FileDownloadTask(urls, xzFile, null); task.setCacheRepository(cacheRepository); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemUtils.java index ec4766eb98..b1dd73bfb8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemUtils.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.util.platform; +import org.jackhuang.hmcl.util.Lang; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -26,6 +28,8 @@ public final class SystemUtils { private SystemUtils() {} + public static final boolean JRE_CAPABILITY_PACK200 = Lang.test(() -> Class.forName("java.util.jar.Pack200")); + public static int callExternalProcess(String... command) throws IOException, InterruptedException { return callExternalProcess(Arrays.asList(command)); } diff --git a/README.md b/README.md index 4817b27d4a..cece0897ce 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,14 @@ If you want to submit a pull request, there're some requirements: * Compiler: Java 1.8. * Do NOT modify `gradle` files. +### Compilation + +Simply execute following command: +```bash +./gradlew clean build +``` +Make sure you have Java installed with Pack200 and JavaFX 8 at least. Liberica full JDK 8~11 is recommended. + ## JVM Options (for debugging) |Parameter|Description| |---------|-----------| From 0d3e204f0d593d7cf4f6fdd3d610fae61d371aa5 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 14 Jun 2020 20:06:19 +0800 Subject: [PATCH 0389/2639] fix: #724 --- .../download/game/GameAssetDownloadTask.java | 10 +---- .../game/GameAssetIndexDownloadTask.java | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 11 deletions(-) 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 775f0fa93f..8ae3ded4c3 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 @@ -65,15 +65,7 @@ public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Versio this.assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId()); this.integrityCheck = integrityCheck; - if (!assetIndexFile.exists() || forceDownloadingIndex) { - dependents.add(new GameAssetIndexDownloadTask(dependencyManager, this.version)); - } else { - try { - JsonUtils.fromNonNullJson(FileUtils.readText(assetIndexFile), AssetIndex.class); - } catch (IOException | JsonParseException e) { - dependents.add(new GameAssetIndexDownloadTask(dependencyManager, this.version)); - } - } + dependents.add(new GameAssetIndexDownloadTask(dependencyManager, this.version, forceDownloadingIndex)); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index a3731b87c6..05b6b0402c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -17,16 +17,26 @@ */ package org.jackhuang.hmcl.download.game; +import com.google.gson.JsonParseException; import org.jackhuang.hmcl.download.AbstractDependencyManager; +import org.jackhuang.hmcl.game.AssetIndex; import org.jackhuang.hmcl.game.AssetIndexInfo; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.DigestUtils; +import org.jackhuang.hmcl.util.Hex; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; +import java.util.logging.Level; + +import static org.jackhuang.hmcl.util.Logging.LOG; /** * This task is to download asset index file provided in minecraft.json. @@ -37,6 +47,7 @@ public final class GameAssetIndexDownloadTask extends Task { private final AbstractDependencyManager dependencyManager; private final Version version; + private final boolean forceDownloading; private final List> dependencies = new LinkedList<>(); /** @@ -45,9 +56,10 @@ public final class GameAssetIndexDownloadTask extends Task { * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ - public GameAssetIndexDownloadTask(AbstractDependencyManager dependencyManager, Version version) { + public GameAssetIndexDownloadTask(AbstractDependencyManager dependencyManager, Version version, boolean forceDownloading) { this.dependencyManager = dependencyManager; this.version = version; + this.forceDownloading = forceDownloading; setSignificance(TaskSignificance.MODERATE); } @@ -60,12 +72,34 @@ public List> getDependencies() { public void execute() { AssetIndexInfo assetIndexInfo = version.getAssetIndex(); File assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId()); + boolean verifyHashCode = StringUtils.isNotBlank(assetIndexInfo.getSha1()) && assetIndexInfo.getUrl().contains(assetIndexInfo.getSha1()); + + if (assetIndexFile.exists() && !forceDownloading) { + // verify correctness of file content + if (verifyHashCode) { + try { + String actualSum = Hex.encodeHex(DigestUtils.digest("SHA-1", assetIndexFile.toPath())); + if (actualSum.equalsIgnoreCase(assetIndexInfo.getSha1())) + return; + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to calculate sha1sum of file " + assetIndexInfo, e); + // continue downloading + } + } else { + try { + JsonUtils.fromNonNullJson(FileUtils.readText(assetIndexFile), AssetIndex.class); + return; + } catch (IOException | JsonParseException ignore) { + } + } + } // We should not check the hash code of asset index file since this file is not consistent // And Mojang will modify this file anytime. So assetIndex.hash might be outdated. FileDownloadTask task = new FileDownloadTask( dependencyManager.getDownloadProvider().injectURLWithCandidates(assetIndexInfo.getUrl()), - assetIndexFile + assetIndexFile, + verifyHashCode ? new FileDownloadTask.IntegrityCheck("SHA-1", assetIndexInfo.getSha1()) : null ); task.setCacheRepository(dependencyManager.getCacheRepository()); dependencies.add(task); From fd24fcc0f2c157e6e58c7543b3492a59e89f1171 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 16 Jun 2020 13:12:41 +0800 Subject: [PATCH 0390/2639] fix: map_to_resources in asset_index.json --- .../src/main/java/org/jackhuang/hmcl/game/AssetIndex.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/AssetIndex.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/AssetIndex.java index 3851e91d2f..8125bce5db 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/AssetIndex.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/AssetIndex.java @@ -33,6 +33,9 @@ public final class AssetIndex { @SerializedName("virtual") private final boolean virtual; + @SerializedName("map_to_resources") + private final boolean mapToResources; + @SerializedName("objects") private final Map objects; @@ -41,12 +44,12 @@ public AssetIndex() { } public AssetIndex(boolean virtual, Map objects) { - this.virtual = virtual; + this.virtual = this.mapToResources = virtual; this.objects = new HashMap<>(objects); } public boolean isVirtual() { - return virtual; + return virtual || mapToResources; } public Map getObjects() { From 6532dc72dbcedb9fc1977f6f89e43daa52af2650 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 16 Jun 2020 13:24:43 +0800 Subject: [PATCH 0391/2639] fix: proxy settings not applied to game --- .../hmcl/setting/VersionSetting.java | 3 +-- .../jackhuang/hmcl/game/LaunchOptions.java | 26 +++++-------------- .../hmcl/launch/DefaultLauncher.java | 25 +++++++++++++++--- 3 files changed, 30 insertions(+), 24 deletions(-) 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 a5532d50a3..a3276d4518 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -554,8 +554,7 @@ public LaunchOptions toLaunchOptions(File gameDir, boolean checkJava) throws Int .setPrecalledCommand(getPreLaunchCommand()) .setNoGeneratedJVMArgs(isNoJVMArgs()); if (config().hasProxy()) { - builder.setProxyHost(config().getProxyHost()); - builder.setProxyPort(config().getProxyPort()); + builder.setProxy(ProxyManager.getProxy()); if (config().hasProxyAuth()) { builder.setProxyUser(config().getProxyUser()); builder.setProxyPass(config().getProxyPass()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java index 7b7aede480..0c43dfce08 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.Serializable; +import java.net.Proxy; /** * @@ -43,8 +44,7 @@ public class LaunchOptions implements Serializable { private boolean fullscreen; private String serverIp; private String wrapper; - private String proxyHost; - private int proxyPort; + private Proxy proxy; private String proxyUser; private String proxyPass; private boolean noGeneratedJVMArgs; @@ -160,17 +160,10 @@ public String getWrapper() { } /** - * The host of the proxy address + * Proxy settings */ - public String getProxyHost() { - return proxyHost; - } - - /** - * the port of the proxy address. - */ - public int getProxyPort() { - return proxyPort; + public Proxy getProxy() { + return proxy; } /** @@ -284,13 +277,8 @@ public Builder setWrapper(String wrapper) { return this; } - public Builder setProxyHost(String proxyHost) { - options.proxyHost = proxyHost; - return this; - } - - public Builder setProxyPort(int proxyPort) { - options.proxyPort = proxyPort; + public Builder setProxy(Proxy proxy) { + options.proxy = proxy; return this; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 148a6fb11d..2d0003c5f9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -41,6 +41,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; @@ -133,6 +135,22 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException res.add("-Dfml.ignorePatchDiscrepancies=true"); } + Proxy proxy = options.getProxy(); + if (proxy != null && StringUtils.isBlank(options.getProxyUser()) && StringUtils.isBlank(options.getProxyPass())) { + InetSocketAddress address = (InetSocketAddress) options.getProxy().address(); + String host = address.getHostString(); + int port = address.getPort(); + if (proxy.type() == Proxy.Type.HTTP) { + res.add("-Dhttp.proxyHost=" + host); + res.add("-Dhttp.proxyPort=" + port); + res.add("-Dhttps.proxyHost=" + host); + res.add("-Dhttps.proxyPort=" + port); + } else if (proxy.type() == Proxy.Type.SOCKS) { + res.add("-DsocksProxyHost=" + host); + res.add("-DsocksProxyPort=" + port); + } + } + LinkedList classpath = new LinkedList<>(); for (Library library : version.getLibraries()) if (library.appliesToCurrentEnvironment() && !library.isNative()) { @@ -182,11 +200,12 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException if (options.isFullscreen()) res.add("--fullscreen"); - if (StringUtils.isNotBlank(options.getProxyHost())) { + if (options.getProxy() != null) { + InetSocketAddress address = (InetSocketAddress) options.getProxy().address(); res.add("--proxyHost"); - res.add(options.getProxyHost()); + res.add(address.getHostString()); res.add("--proxyPort"); - res.add(String.valueOf(options.getProxyPort())); + res.add(String.valueOf(address.getPort())); if (StringUtils.isNotBlank(options.getProxyUser()) && StringUtils.isNotBlank(options.getProxyPass())) { res.add("--proxyUser"); res.add(options.getProxyUser()); From 3119b4d88d5efbf308d8c2d68fa6fc3e182a19aa Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 16 Jun 2020 14:30:11 +0800 Subject: [PATCH 0392/2639] fix: #728 --- .../jackhuang/hmcl/game/LauncherHelper.java | 4 + .../game/GameVerificationFixTask.java | 82 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.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 b5706a9242..8bd37b335a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -26,6 +26,7 @@ import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; +import org.jackhuang.hmcl.download.game.GameVerificationFixTask; import org.jackhuang.hmcl.download.game.LibraryDownloadException; import org.jackhuang.hmcl.launch.NotDecompressingNativesException; import org.jackhuang.hmcl.launch.PermissionException; @@ -149,6 +150,9 @@ else if ("Server".equals(configuration.getType())) return null; } }))).withStage("launch.state.dependencies") + .thenComposeAsync(() -> { + return gameVersion.map(s -> new GameVerificationFixTask(dependencyManager, s, version)).orElse(null); + }) .thenComposeAsync(Task.supplyAsync(() -> { try { return account.logIn(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java new file mode 100644 index 0000000000..b76ca25bed --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java @@ -0,0 +1,82 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.download.game; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.game.GameVersion; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.CacheRepository; +import org.jackhuang.hmcl.util.io.CompressingUtils; +import org.jackhuang.hmcl.util.versioning.VersionNumber; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +/** + * Remove class digital verification file in game jar + * @author huangyuhui + */ +public final class GameVerificationFixTask extends Task { + private final DefaultDependencyManager dependencyManager; + private final String gameVersion; + private final Version version; + private final List> dependencies = new LinkedList<>(); + + public GameVerificationFixTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version) { + this.dependencyManager = dependencyManager; + this.gameVersion = gameVersion; + this.version = version; + + if (!version.isResolved()) { + throw new IllegalArgumentException("GameVerificationFixTask requires a resolved game version"); + } + + setSignificance(TaskSignificance.MODERATE); + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public void execute() throws IOException { + File jar = dependencyManager.getGameRepository().getVersionJar(version); + LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version); + + if (jar.exists() && VersionNumber.VERSION_COMPARATOR.compare(gameVersion, "1.6") < 0 && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) { + try (FileSystem fs = CompressingUtils.createWritableZipFileSystem(jar.toPath(), StandardCharsets.UTF_8)) { + Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.DSA")); + Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.SF")); + } + } + } + +} From 82763f3c323184713b2aa8900c13d8889881bcfa Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 16 Jun 2020 14:35:21 +0800 Subject: [PATCH 0393/2639] feat: font family override --- HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java | 7 ++++--- HMCL/src/main/resources/assets/css/custom.css | 2 ++ README.md | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java index ce8a1af0ce..66a4cf112b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java @@ -87,9 +87,10 @@ public String[] getStylesheets() { File temp = File.createTempFile("hmcl", ".css"); FileUtils.writeText(temp, IOUtils.readFullyAsString(ResourceNotFoundError.getResourceAsStream("/assets/css/custom.css")) .replace("%base-color%", color) - .replace("%base-rippler-color%", String.format("rgba(%d, %d, %d, 0.3)", (int)Math.ceil(paint.getRed() * 256), (int)Math.ceil(paint.getGreen() * 256), (int)Math.ceil(paint.getBlue() * 256))) - .replace("%disabled-font-color%", String.format("rgba(%d, %d, %d, 0.7)", (int)Math.ceil(textFill.getRed() * 256), (int)Math.ceil(textFill.getGreen() * 256), (int)Math.ceil(textFill.getBlue() * 256))) - .replace("%font-color%", getColorDisplayName(getForegroundColor()))); + .replace("%base-rippler-color%", String.format("rgba(%d, %d, %d, 0.3)", (int) Math.ceil(paint.getRed() * 256), (int) Math.ceil(paint.getGreen() * 256), (int) Math.ceil(paint.getBlue() * 256))) + .replace("%disabled-font-color%", String.format("rgba(%d, %d, %d, 0.7)", (int) Math.ceil(textFill.getRed() * 256), (int) Math.ceil(textFill.getGreen() * 256), (int) Math.ceil(textFill.getBlue() * 256))) + .replace("%font-color%", getColorDisplayName(getForegroundColor())) + .replace("%font%", Optional.ofNullable(System.getProperty("hmcl.font.override")).map(fontFamily -> "-fx-font-family: " + fontFamily + ";").orElse(""))); css = temp.toURI().toString(); } catch (IOException | NullPointerException e) { Logging.LOG.log(Level.SEVERE, "Unable to create theme stylesheet. Fallback to blue theme.", e); diff --git a/HMCL/src/main/resources/assets/css/custom.css b/HMCL/src/main/resources/assets/css/custom.css index 5636c87288..fea9fbeba1 100644 --- a/HMCL/src/main/resources/assets/css/custom.css +++ b/HMCL/src/main/resources/assets/css/custom.css @@ -22,4 +22,6 @@ -fx-base-rippler-color: %base-rippler-color%; -fx-base-disabled-text-fill: %disabled-font-color%; -fx-base-text-fill: %font-color%; + + %font% } \ No newline at end of file diff --git a/README.md b/README.md index cece0897ce..f767276ed1 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Make sure you have Java installed with Pack200 and JavaFX 8 at least. Liberica f |Parameter|Description| |---------|-----------| |`-Dhmcl.self_integrity_check.disable=true`|Bypass the self integrity check when checking for update.| +|`-Dhmcl.font.override=`|Override font family.| |`-Dhmcl.version.override=`|Override the version number.| |`-Dhmcl.update_source.override=`|Override the update source.| |`-Dhmcl.authlibinjector.location=`|Use specified authlib-injector (instead of downloading one).| From 891b64ee0fb9bb23647264b77c2163d7292d7cfe Mon Sep 17 00:00:00 2001 From: haarlemmer Date: Fri, 19 Jun 2020 19:20:32 +0800 Subject: [PATCH 0394/2639] Modify some Chinese (Simplified) translations. --- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 fbcf6f54f3..42dfe31429 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -88,7 +88,7 @@ button.no=否 button.ok=确定 button.refresh=刷新 button.remove=删除 -button.remove.confirm=您确定要删除吗?该操作无法撤销! +button.remove.confirm=您确定要删除吗?此操作无法撤销! button.save=保存 button.yes=是 @@ -141,7 +141,7 @@ install.failed.downloading=安装失败,部分文件未能完成下载 install.failed.downloading.detail=未能下载文件:%s install.failed.downloading.timeout=下载超时:%s install.failed.install_online=无法识别要安装的软件 -install.failed.malformed=刚才下载的文件格式损坏。您可以切换到其他下载源来解决此问题。 +install.failed.malformed=下载的文件格式损坏。您可以切换到其他下载源来解决此问题。 install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 与 Forge 同时安装在 Minecraft 1.13 及以上版本 install.failed.version_mismatch=该软件需要的游戏版本为 %s,但实际的游戏版本为 %s。 install.installer.change_version=%s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除 @@ -177,7 +177,7 @@ launch.advice.different_platform=您的系统是 64 位,但是 Java 是 32 位 launch.advice.forge2760_liteloader=Forge 2760 与 LiteLoader 不兼容。请删除 LiteLoader 或者更换 Forge 至 2773 或更新的版本。是否继续启动? launch.advice.forge28_2_2_optifine=Forge 28.2.2 或更高版本与 OptiFine 不兼容。请更换 Forge 至 28.2.1 或更低版本。是否继续启动? launch.advice.java8_1_13=Minecraft 1.13 只支持 Java 8 或更高版本,请使用 Java 8 或最新版本。 -launch.advice.java8_51_1_13=低于 1.8.0_51 的 Java 版本可能会导致 Minecraft 1.13 崩溃。建议您到 https://java.com 安装最新版的 Java 8。 +launch.advice.java8_51_1_13=低于 1.8.0_51 的 Java 版本可能会导致 Minecraft 1.13 崩溃。建议您到 https://java.com 安装 Java 8。 launch.advice.java9=低于 1.13 的有安装 Mod 的 Minecraft 版本不支持 Java 9 或更高版本,请使用 Java 8。 launch.advice.newer_java=检测到您未使用 Java 8 及更新版本,Java 8 能使游戏更流畅,而且 Minecraft 1.12 及更新版本和很多 Mod 强制需要 Java 8。 launch.advice.not_enough_space=您设置的内存大小过大,由于超过了系统内存大小 %dMB,所以可能影响游戏体验或无法启动游戏。是否继续启动? @@ -241,7 +241,7 @@ modpack.desc=描述你要制作的整合包,比如整合包注意事项和更 modpack.description=整合包描述 modpack.enter_name=给游戏起个你喜欢的名字 modpack.export=导出整合包 -modpack.export.as=请选择整合包类型。若你无法决定,请选择 HMCL 类型。 +modpack.export.as=请选择整合包类型 (若无法决定,请选择 HMCL 类型) modpack.file_api=整合包下载链接前缀 modpack.files.blueprints=BuildCraft 蓝图 modpack.files.config=Mod 配置文件 From 63082f5a5e25cbdaecfa2fef140bb5eb28fcaf9a Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 21 Jun 2020 17:12:51 +0800 Subject: [PATCH 0395/2639] fix: #731 --- .../download/AdaptedDownloadProvider.java | 28 +++++++++---------- .../hmcl/download/DownloadProvider.java | 2 +- .../download/game/LibraryDownloadTask.java | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java index 6f223553f8..9dd64cc63b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AdaptedDownloadProvider.java @@ -22,6 +22,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * The download provider that changes the real download source in need. @@ -59,26 +60,25 @@ public String injectURL(String baseURL) { return getPreferredDownloadProvider().injectURL(baseURL); } + @Override + public List getAssetObjectCandidates(String assetObjectLocation) { + return downloadProviderCandidates.stream() + .flatMap(d -> d.getAssetObjectCandidates(assetObjectLocation).stream()) + .collect(Collectors.toList()); + } + @Override public List injectURLWithCandidates(String baseURL) { - List d = downloadProviderCandidates; - List results = new ArrayList<>(d.size()); - for (DownloadProvider downloadProvider : d) { - results.add(NetworkUtils.toURL(downloadProvider.injectURL(baseURL))); - } - return results; + return downloadProviderCandidates.stream() + .flatMap(d -> d.injectURLWithCandidates(baseURL).stream()) + .collect(Collectors.toList()); } @Override public List injectURLsWithCandidates(List urls) { - List d = downloadProviderCandidates; - List results = new ArrayList<>(d.size()); - for (DownloadProvider downloadProvider : d) { - for (String baseURL : urls) { - results.add(NetworkUtils.toURL(downloadProvider.injectURL(baseURL))); - } - } - return results; + return downloadProviderCandidates.stream() + .flatMap(d -> d.injectURLsWithCandidates(urls).stream()) + .collect(Collectors.toList()); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java index 7ef333044c..a1f6fd45df 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java @@ -60,7 +60,7 @@ default List getAssetObjectCandidates(String assetObjectLocation) { * @return the URL that is equivalent to [baseURL], but belongs to your own service provider. */ default List injectURLWithCandidates(String baseURL) { - return Collections.singletonList(NetworkUtils.toURL(baseURL)); + return Collections.singletonList(NetworkUtils.toURL(injectURL(baseURL))); } default List injectURLsWithCandidates(List urls) { 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 871d17942b..106fbc3672 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 @@ -151,7 +151,7 @@ private boolean testURLExistence(String rawUrl) { try { return NetworkUtils.urlExists(xzURL); } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to test for url existence: " + rawUrl + ".pack.xz", e); + LOG.log(Level.WARNING, "Failed to test for url existence: " + url + ".pack.xz", e); } } } From 1208d6dabc73d33b6c0730321c99eceb8ce63247 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 21 Jun 2020 18:18:20 +0800 Subject: [PATCH 0396/2639] feat: decorator shadow --- .../org/jackhuang/hmcl/ui/Controllers.java | 10 +- .../hmcl/ui/decorator/Decorator.java | 6 + .../ui/decorator/DecoratorController.java | 2 +- .../hmcl/ui/decorator/DecoratorSkin.java | 111 +++++++++--------- HMCL/src/main/resources/assets/css/root.css | 9 +- 5 files changed, 78 insertions(+), 60 deletions(-) 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 92c92ef2e2..8407b81286 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -22,7 +22,9 @@ import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.layout.Region; +import javafx.scene.paint.Color; import javafx.stage.Stage; +import javafx.stage.StageStyle; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.EnumCommonDirectory; @@ -123,15 +125,17 @@ public static void initialize(Stage stage) { Task.runAsync(JavaVersion::initialize).start(); - scene = new Scene(decorator.getDecorator(), 802, 482); - stage.setMinHeight(482); - stage.setMinWidth(802); + scene = new Scene(decorator.getDecorator()); + scene.setFill(Color.TRANSPARENT); + stage.setMinHeight(482 + 32); + stage.setMinWidth(802 + 32); decorator.getDecorator().prefWidthProperty().bind(scene.widthProperty()); decorator.getDecorator().prefHeightProperty().bind(scene.heightProperty()); scene.getStylesheets().setAll(config().getTheme().getStylesheets()); stage.getIcons().add(newImage("/assets/img/icon.png")); stage.setTitle(Metadata.TITLE); + stage.initStyle(StageStyle.TRANSPARENT); stage.setScene(scene); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java index e33d7ba83f..eecb72e608 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java @@ -22,12 +22,16 @@ import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; +import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.control.Control; import javafx.scene.control.Skin; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.CornerRadii; import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -55,6 +59,8 @@ public class Decorator extends Control { public Decorator(Stage primaryStage) { this.primaryStage = primaryStage; + setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY))); + primaryStage.initStyle(StageStyle.UNDECORATED); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 7a50d4c55d..a6db838393 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -133,7 +133,7 @@ private boolean switchedToNewUI() { // ==== Background ==== private void setupBackground() { - decorator.backgroundProperty().bind( + decorator.contentBackgroundProperty().bind( Bindings.createObjectBinding( () -> { Image image = null; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 651fb74d56..99116b16d2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -50,7 +50,7 @@ public class DecoratorSkin extends SkinBase { private static final SVGGlyph minus = Lang.apply(new SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE), glyph -> { glyph.setSize(12, 2); glyph.setTranslateY(4); }); - private final StackPane parent; + private final StackPane root, parent; private final StackPane titleContainer; private final Stage primaryStage; private final TransitionPane navBarPane; @@ -72,15 +72,20 @@ public DecoratorSkin(Decorator control) { minus.fillProperty().bind(Theme.foregroundFillBinding()); Decorator skinnable = getSkinnable(); + root = new StackPane(); + root.getStyleClass().add("window"); + parent = new StackPane(); - parent.getStyleClass().add("window"); - parent.backgroundProperty().bind(skinnable.backgroundProperty()); + parent.getStyleClass().add("body"); + parent.backgroundProperty().bind(skinnable.contentBackgroundProperty()); parent.setPickOnBounds(false); parent.prefHeightProperty().bind(control.prefHeightProperty()); parent.prefWidthProperty().bind(control.prefWidthProperty()); - parent.setOnMouseReleased(this::onMouseReleased); - parent.setOnMouseDragged(this::onMouseDragged); - parent.setOnMouseMoved(this::onMouseMoved); + root.setOnMouseReleased(this::onMouseReleased); + root.setOnMouseDragged(this::onMouseDragged); + root.setOnMouseMoved(this::onMouseMoved); + + root.getChildren().setAll(parent); // animation layer at bottom { @@ -93,9 +98,9 @@ public DecoratorSkin(Decorator control) { } StackPane wrapper = new StackPane(); - BorderPane root = new BorderPane(); - root.getStyleClass().addAll("jfx-decorator"); - wrapper.getChildren().setAll(root); + BorderPane frame = new BorderPane(); + frame.getStyleClass().addAll("jfx-decorator"); + wrapper.getChildren().setAll(frame); skinnable.setDrawerWrapper(wrapper); parent.getChildren().add(wrapper); @@ -132,7 +137,7 @@ public DecoratorSkin(Decorator control) { container.getChildren().add(floatLayer); } - root.setCenter(container); + frame.setCenter(container); titleContainer = new StackPane(); titleContainer.setPickOnBounds(false); @@ -174,7 +179,7 @@ public DecoratorSkin(Decorator control) { titleBar.setCenter(navBarPane); titleBar.setRight(buttonsContainerPlaceHolder); } - root.setTop(titleContainer); + frame.setTop(titleContainer); { HBox buttonsContainer = new HBox(); @@ -204,7 +209,7 @@ public DecoratorSkin(Decorator control) { parent.getChildren().add(layer); } - getChildren().add(parent); + getChildren().add(root); } private Node createNavBar(Decorator skinnable, boolean titleBarTransparent, double leftPaneWidth, boolean canBack, boolean canClose, boolean showCloseAsHome, boolean canRefresh, String title, Node titleNode) { @@ -293,19 +298,19 @@ private void updateInitMouseValues(MouseEvent mouseEvent) { } private boolean isRightEdge(double x, double y, Bounds boundsInParent) { - return x < parent.getWidth() && x >= parent.getWidth() - parent.snappedLeftInset(); + return x < root.getWidth() && x >= root.getWidth() - root.snappedLeftInset(); } private boolean isTopEdge(double x, double y, Bounds boundsInParent) { - return y >= 0 && y <= parent.snappedTopInset(); + return y >= 0 && y <= root.snappedTopInset(); } private boolean isBottomEdge(double x, double y, Bounds boundsInParent) { - return y < parent.getHeight() && y >= parent.getHeight() - parent.snappedLeftInset(); + return y < root.getHeight() && y >= root.getHeight() - root.snappedLeftInset(); } private boolean isLeftEdge(double x, double y, Bounds boundsInParent) { - return x >= 0 && x <= parent.snappedLeftInset(); + return x >= 0 && x <= root.snappedLeftInset(); } private boolean setStageWidth(double width) { @@ -341,48 +346,46 @@ protected void onMouseMoved(MouseEvent mouseEvent) { updateInitMouseValues(mouseEvent); if (primaryStage.isResizable()) { double x = mouseEvent.getX(), y = mouseEvent.getY(); - Bounds boundsInParent = parent.getBoundsInParent(); - if (parent.getBorder() != null && parent.getBorder().getStrokes().size() > 0) { - double diagonalSize = parent.snappedLeftInset() + 10; - if (this.isRightEdge(x, y, boundsInParent)) { - if (y < diagonalSize) { - parent.setCursor(Cursor.NE_RESIZE); - } else if (y > parent.getHeight() - diagonalSize) { - parent.setCursor(Cursor.SE_RESIZE); - } else { - parent.setCursor(Cursor.E_RESIZE); - } - } else if (this.isLeftEdge(x, y, boundsInParent)) { - if (y < diagonalSize) { - parent.setCursor(Cursor.NW_RESIZE); - } else if (y > parent.getHeight() - diagonalSize) { - parent.setCursor(Cursor.SW_RESIZE); - } else { - parent.setCursor(Cursor.W_RESIZE); - } - } else if (this.isTopEdge(x, y, boundsInParent)) { - if (x < diagonalSize) { - parent.setCursor(Cursor.NW_RESIZE); - } else if (x > parent.getWidth() - diagonalSize) { - parent.setCursor(Cursor.NE_RESIZE); - } else { - parent.setCursor(Cursor.N_RESIZE); - } - } else if (this.isBottomEdge(x, y, boundsInParent)) { - if (x < diagonalSize) { - parent.setCursor(Cursor.SW_RESIZE); - } else if (x > parent.getWidth() - diagonalSize) { - parent.setCursor(Cursor.SE_RESIZE); - } else { - parent.setCursor(Cursor.S_RESIZE); - } + Bounds boundsInParent = root.getBoundsInParent(); + double diagonalSize = root.snappedLeftInset() + 10; + if (this.isRightEdge(x, y, boundsInParent)) { + if (y < diagonalSize) { + root.setCursor(Cursor.NE_RESIZE); + } else if (y > root.getHeight() - diagonalSize) { + root.setCursor(Cursor.SE_RESIZE); } else { - parent.setCursor(Cursor.DEFAULT); + root.setCursor(Cursor.E_RESIZE); } + } else if (this.isLeftEdge(x, y, boundsInParent)) { + if (y < diagonalSize) { + root.setCursor(Cursor.NW_RESIZE); + } else if (y > root.getHeight() - diagonalSize) { + root.setCursor(Cursor.SW_RESIZE); + } else { + root.setCursor(Cursor.W_RESIZE); + } + } else if (this.isTopEdge(x, y, boundsInParent)) { + if (x < diagonalSize) { + root.setCursor(Cursor.NW_RESIZE); + } else if (x > root.getWidth() - diagonalSize) { + root.setCursor(Cursor.NE_RESIZE); + } else { + root.setCursor(Cursor.N_RESIZE); + } + } else if (this.isBottomEdge(x, y, boundsInParent)) { + if (x < diagonalSize) { + root.setCursor(Cursor.SW_RESIZE); + } else if (x > root.getWidth() - diagonalSize) { + root.setCursor(Cursor.SE_RESIZE); + } else { + root.setCursor(Cursor.S_RESIZE); + } + } else { + root.setCursor(Cursor.DEFAULT); } } } else { - parent.setCursor(Cursor.DEFAULT); + root.setCursor(Cursor.DEFAULT); } } @@ -398,7 +401,7 @@ protected void onMouseDragged(MouseEvent mouseEvent) { this.newY = mouseEvent.getScreenY(); double deltaX = this.newX - this.initX; double deltaY = this.newY - this.initY; - Cursor cursor = parent.getCursor(); + Cursor cursor = root.getCursor(); if (Cursor.E_RESIZE == cursor) { this.setStageWidth(this.primaryStage.getWidth() + deltaX); mouseEvent.consume(); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 0dc99cd848..c3fe72dd2f 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -1146,8 +1146,13 @@ } .window { - -fx-border-color: black; - -fx-border-width: 1; + -fx-background-color: transparent; + -fx-padding: 16; +} + +.body { + -fx-border-radius: 5; + -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.4), 20, 0.3, 0.0, 0.0); } .debug-border { From bd18355a1a02a8f6a927edd7dadadbf18857e6e9 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 26 Jun 2020 21:25:26 +0800 Subject: [PATCH 0397/2639] fix: NPE --- .../hmcl/launch/DefaultLauncher.java | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 2d0003c5f9..904087ca0c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -138,16 +138,18 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException Proxy proxy = options.getProxy(); if (proxy != null && StringUtils.isBlank(options.getProxyUser()) && StringUtils.isBlank(options.getProxyPass())) { InetSocketAddress address = (InetSocketAddress) options.getProxy().address(); - String host = address.getHostString(); - int port = address.getPort(); - if (proxy.type() == Proxy.Type.HTTP) { - res.add("-Dhttp.proxyHost=" + host); - res.add("-Dhttp.proxyPort=" + port); - res.add("-Dhttps.proxyHost=" + host); - res.add("-Dhttps.proxyPort=" + port); - } else if (proxy.type() == Proxy.Type.SOCKS) { - res.add("-DsocksProxyHost=" + host); - res.add("-DsocksProxyPort=" + port); + if (address != null) { + String host = address.getHostString(); + int port = address.getPort(); + if (proxy.type() == Proxy.Type.HTTP) { + res.add("-Dhttp.proxyHost=" + host); + res.add("-Dhttp.proxyPort=" + port); + res.add("-Dhttps.proxyHost=" + host); + res.add("-Dhttps.proxyPort=" + port); + } else if (proxy.type() == Proxy.Type.SOCKS) { + res.add("-DsocksProxyHost=" + host); + res.add("-DsocksProxyPort=" + port); + } } } @@ -202,15 +204,17 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException if (options.getProxy() != null) { InetSocketAddress address = (InetSocketAddress) options.getProxy().address(); - res.add("--proxyHost"); - res.add(address.getHostString()); - res.add("--proxyPort"); - res.add(String.valueOf(address.getPort())); - if (StringUtils.isNotBlank(options.getProxyUser()) && StringUtils.isNotBlank(options.getProxyPass())) { - res.add("--proxyUser"); - res.add(options.getProxyUser()); - res.add("--proxyPass"); - res.add(options.getProxyPass()); + if (address != null) { + res.add("--proxyHost"); + res.add(address.getHostString()); + res.add("--proxyPort"); + res.add(String.valueOf(address.getPort())); + if (StringUtils.isNotBlank(options.getProxyUser()) && StringUtils.isNotBlank(options.getProxyPass())) { + res.add("--proxyUser"); + res.add(options.getProxyUser()); + res.add("--proxyPass"); + res.add(options.getProxyPass()); + } } } From dc03f28d56979641cefecc5f6bc27896589e5357 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 26 Jun 2020 21:29:47 +0800 Subject: [PATCH 0398/2639] refactor: WizardDisplayer --- .../decorator/DecoratorWizardDisplayer.java | 37 ++++-- .../hmcl/ui/download/LocalModpackPage.java | 2 +- .../ui/wizard/AbstractWizardDisplayer.java | 20 +-- .../ui/wizard/DefaultWizardDisplayer.java | 114 ------------------ .../TaskExecutorDialogWizardDisplayer.java | 9 +- .../org/jackhuang/hmcl/ui/wizard/Wizard.java | 31 ----- .../hmcl/ui/wizard/WizardController.java | 10 ++ .../hmcl/ui/wizard/WizardDisplayer.java | 13 +- .../main/resources/assets/fxml/wizard.fxml | 49 -------- .../download/game/GameRemoteVersions.java | 9 +- 10 files changed, 72 insertions(+), 222 deletions(-) delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Wizard.java delete mode 100644 HMCL/src/main/resources/assets/fxml/wizard.fxml diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java index c6bc304772..b995b1c1e3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java @@ -19,16 +19,28 @@ import javafx.scene.Node; import javafx.scene.control.SkinBase; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.Navigator; import org.jackhuang.hmcl.ui.construct.PageCloseEvent; import org.jackhuang.hmcl.ui.wizard.*; +import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; -public class DecoratorWizardDisplayer extends DecoratorTransitionPage implements TaskExecutorDialogWizardDisplayer { +public class DecoratorWizardDisplayer extends DecoratorTransitionPage implements WizardDisplayer { private final WizardController wizardController = new WizardController(this); - private final Queue cancelQueue = new ConcurrentLinkedQueue<>(); + private final WizardDisplayer displayer = new TaskExecutorDialogWizardDisplayer(new ConcurrentLinkedQueue<>()) { + @Override + public void onEnd() { + super.onEnd(); + fireEvent(new PageCloseEvent()); + } + + @Override + public void navigateTo(Node page, Navigation.NavigationDirection nav) { + } + }; private final String category; @@ -46,27 +58,23 @@ public DecoratorWizardDisplayer(WizardProvider provider, String category) { } @Override - public WizardController getWizardController() { - return wizardController; - } - - @Override - public Queue getCancelQueue() { - return cancelQueue; + public void onStart() { + displayer.onStart(); } @Override - public void onStart() { - + public void onCancel() { + displayer.onCancel(); } @Override public void onEnd() { - fireEvent(new PageCloseEvent()); + displayer.onEnd(); } @Override public void navigateTo(Node page, Navigation.NavigationDirection nav) { + displayer.navigateTo(page, nav); navigate(page, nav.getAnimation().getAnimationProducer()); String prefix = category == null ? "" : category + " - "; @@ -86,6 +94,11 @@ public void navigateTo(Node page, Navigation.NavigationDirection nav) { } } + @Override + public void handleTask(Map settings, Task task) { + displayer.handleTask(settings, task); + } + @Override public boolean isPageCloseable() { return true; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index e740800bef..32864df629 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -101,7 +101,7 @@ public LocalModpackPage(WizardController controller) { chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("modpack"), "*.zip")); selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile == null) { - Platform.runLater(controller::onEnd); + controller.onEnd(); return; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java index 4a88ce0115..c122cb0f19 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java @@ -26,32 +26,34 @@ import java.util.Map; import java.util.Queue; -public interface AbstractWizardDisplayer extends WizardDisplayer { - WizardController getWizardController(); +public abstract class AbstractWizardDisplayer implements WizardDisplayer { + private final Queue cancelQueue; - Queue getCancelQueue(); + public AbstractWizardDisplayer(Queue cancelQueue) { + this.cancelQueue = cancelQueue; + } @Override - default void handleTask(Map settings, Task task) { + public void handleTask(Map settings, Task task) { TaskExecutor executor = task.withRunAsync(Schedulers.javafx(), this::navigateToSuccess).executor(); TaskListPane pane = new TaskListPane(); pane.setExecutor(executor); navigateTo(pane, Navigation.NavigationDirection.FINISH); - getCancelQueue().add(executor); + cancelQueue.add(executor); executor.start(); } @Override - default void onCancel() { - while (!getCancelQueue().isEmpty()) { - Object x = getCancelQueue().poll(); + public void onCancel() { + while (!cancelQueue.isEmpty()) { + Object x = cancelQueue.poll(); if (x instanceof TaskExecutor) ((TaskExecutor) x).cancel(); else if (x instanceof Thread) ((Thread) x).interrupt(); else throw new IllegalStateException("Unrecognized cancel queue element: " + x); } } - default void navigateToSuccess() { + void navigateToSuccess() { navigateTo(new Label("Successful"), Navigation.NavigationDirection.FINISH); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java deleted file mode 100644 index f24e678764..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.ui.wizard; - -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXToolbar; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.ui.FXUtils; -import org.jackhuang.hmcl.ui.animation.TransitionPane; -import org.jackhuang.hmcl.util.StringUtils; - -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -public class DefaultWizardDisplayer extends StackPane implements AbstractWizardDisplayer { - - private final String prefix; - private final WizardController wizardController; - private final Queue cancelQueue = new ConcurrentLinkedQueue<>(); - - private Node nowPage; - - @FXML - private TransitionPane root; - @FXML - private JFXButton backButton; - @FXML - private JFXToolbar toolbar; - @FXML - private JFXButton refreshButton; - @FXML - private Label titleLabel; - - public DefaultWizardDisplayer(String prefix, WizardProvider wizardProvider) { - this.prefix = prefix; - - FXUtils.loadFXML(this, "/assets/fxml/wizard.fxml"); - toolbar.setEffect(null); - - wizardController = new WizardController(this); - wizardController.setProvider(wizardProvider); - } - - @Override - public WizardController getWizardController() { - return wizardController; - } - - @Override - public Queue getCancelQueue() { - return cancelQueue; - } - - @Override - public void onStart() { - } - - @Override - public void onEnd() { - } - - @Override - public void onCancel() { - } - - @Override - public void navigateTo(Node page, Navigation.NavigationDirection nav) { - backButton.setDisable(!wizardController.canPrev()); - root.setContent(page, nav.getAnimation().getAnimationProducer()); - String title = StringUtils.isBlank(prefix) ? "" : prefix + " - "; - if (page instanceof WizardPage) - titleLabel.setText(title + ((WizardPage) page).getTitle()); - refreshButton.setVisible(page instanceof Refreshable); - nowPage = page; - } - - @FXML - private void initialize() { - wizardController.onStart(); - } - - @FXML - private void back() { - wizardController.onPrev(true); - } - - @FXML - private void close() { - wizardController.onCancel(); - } - - @FXML - private void refresh() { - ((Refreshable) nowPage).refresh(); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 9203ecfebf..91b39d6bd7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -28,14 +28,19 @@ import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; +import java.util.Queue; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer { +public abstract class TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer { + + public TaskExecutorDialogWizardDisplayer(Queue cancelQueue) { + super(cancelQueue); + } @Override - default void handleTask(Map settings, Task task) { + public void handleTask(Map settings, Task task) { TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> { it.fireEvent(new DialogCloseEvent()); onEnd(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Wizard.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Wizard.java deleted file mode 100644 index 7b91bf8beb..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Wizard.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.ui.wizard; - -import javafx.scene.Node; - -public final class Wizard { - - public static Node createWizard(WizardProvider provider) { - return createWizard("", provider); - } - - public static Node createWizard(String namespace, WizardProvider provider) { - return new DefaultWizardDisplayer(namespace, provider); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java index 702cf4ec62..2d97e4a872 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java @@ -28,6 +28,7 @@ public class WizardController implements Navigation { private WizardProvider provider = null; private final Map settings = new HashMap<>(); private final Stack pages = new Stack<>(); + private boolean stopped = false; public WizardController(WizardDisplayer displayer) { this.displayer = displayer; @@ -60,6 +61,10 @@ public void onStart() { Node page = navigatingTo(0); pages.push(page); + if (stopped) { // navigatingTo may stop this wizard. + return; + } + if (page instanceof WizardPage) ((WizardPage) page).onNavigate(settings); @@ -77,6 +82,10 @@ public void onNext() { public void onNext(Node page) { pages.push(page); + if (stopped) { // navigatingTo may stop this wizard. + return; + } + if (page instanceof WizardPage) ((WizardPage) page).onNavigate(settings); @@ -122,6 +131,7 @@ public void onFinish() { @Override public void onEnd() { + stopped = true; settings.clear(); pages.clear(); displayer.onEnd(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java index 95d0414d97..1d1cb5c04a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java @@ -23,9 +23,16 @@ import java.util.Map; public interface WizardDisplayer { - void onStart(); - void onEnd(); - void onCancel(); + default void onStart() { + } + + default void onEnd() { + } + + default void onCancel() { + } + void navigateTo(Node page, Navigation.NavigationDirection nav); + void handleTask(Map settings, Task task); } diff --git a/HMCL/src/main/resources/assets/fxml/wizard.fxml b/HMCL/src/main/resources/assets/fxml/wizard.fxml deleted file mode 100644 index a7f3dfd346..0000000000 --- a/HMCL/src/main/resources/assets/fxml/wizard.fxml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersions.java index d8796a9b56..6762fb111c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersions.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersions.java @@ -17,8 +17,10 @@ */ package org.jackhuang.hmcl.download.game; +import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import org.jackhuang.hmcl.util.Immutable; +import org.jackhuang.hmcl.util.gson.Validation; import java.util.Collections; import java.util.List; @@ -28,7 +30,7 @@ * @author huangyuhui */ @Immutable -public final class GameRemoteVersions { +public final class GameRemoteVersions implements Validation { @SerializedName("versions") private final List versions; @@ -57,4 +59,9 @@ public List getVersions() { return versions; } + @Override + public void validate() throws JsonParseException { + if (versions == null) + throw new JsonParseException("GameRemoteVersions.versions cannot be null"); + } } From 3c224198e73f45a6df714690115c85b3448318a3 Mon Sep 17 00:00:00 2001 From: jihuayu <8042833@qq.com> Date: Tue, 14 Jul 2020 23:13:33 +0800 Subject: [PATCH 0399/2639] fix:fix #744 --- .../org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java index ee844b5efd..256072a069 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java @@ -32,11 +32,11 @@ public class GameAdvancedListItem extends AdvancedListItem { public GameAdvancedListItem() { tooltip = new Tooltip(); - FXUtils.installFastTooltip(this, tooltip); FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), version -> { if (version != null && Profiles.getSelectedProfile() != null && Profiles.getSelectedProfile().getRepository().hasVersion(version)) { + FXUtils.installFastTooltip(this, tooltip); setTitle(version); setSubtitle(null); setImage(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version)); From a60c28833590f034608dce86bb95624a32b0f2d8 Mon Sep 17 00:00:00 2001 From: jihuayu <8042833@qq.com> Date: Tue, 14 Jul 2020 23:31:25 +0800 Subject: [PATCH 0400/2639] fix:fix #744 (2) --- .../org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java | 1 + 1 file changed, 1 insertion(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java index 256072a069..000e851564 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java @@ -42,6 +42,7 @@ public GameAdvancedListItem() { setImage(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version)); tooltip.setText(version); } else { + Tooltip.uninstall(this,tooltip); setTitle(i18n("version.empty")); setSubtitle(i18n("version.empty.add")); setImage(newImage("/assets/img/grass.png")); From 61447f096481379e8044cbb72a30f4181c2934ca Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 14:20:42 +0800 Subject: [PATCH 0401/2639] fix: #741 --- HMCLauncher/HMCL/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp index 80717d8c8e..f7ba721c8d 100644 --- a/HMCLauncher/HMCL/main.cpp +++ b/HMCLauncher/HMCL/main.cpp @@ -41,11 +41,11 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd if (is64Bit) { - LaunchJVM(L"jre-x64\\bin\\javaw.exe", exeName); + RawLaunchJVM(L"jre-x64\\bin\\javaw.exe", exeName); } else { - LaunchJVM(L"jre-x86\\bin\\javaw.exe", exeName); + RawLaunchJVM(L"jre-x86\\bin\\javaw.exe", exeName); } if (FindJava(path)) From d6859d19568fdb880359c99babb3548474e58e60 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 14:21:11 +0800 Subject: [PATCH 0402/2639] fix: not stop waiting for MC 1.0 launch --- 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 8bd37b335a..3ffd1a3fc2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -580,7 +580,7 @@ public synchronized void onLog(String log, Log4jLevel level) { Platform.runLater(() -> logWindow.logLine(filteredLog, level)); } - if (!lwjgl && (filteredLog.toLowerCase().contains("lwjgl version") || !detectWindow)) { + if (!lwjgl && (filteredLog.toLowerCase().contains("lwjgl version") || filteredLog.toLowerCase().contains("lwjgl openal") || !detectWindow)) { lwjgl = true; finishLaunch(); } From 4ce0a838453f8ed261142449e1cee778e51d7e3e Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 15:19:53 +0800 Subject: [PATCH 0403/2639] feat: display new version of updated modpack. Closes #748. --- .../hmcl/game/HMCLModpackInstallTask.java | 2 +- .../hmcl/ui/construct/TwoLineListItem.java | 31 ++++++++++++++++++- .../hmcl/ui/download/LocalModpackPage.java | 2 +- .../hmcl/ui/download/RemoteModpackPage.java | 2 +- .../jackhuang/hmcl/ui/versions/GameItem.java | 20 ++++++++++++ .../hmcl/ui/versions/GameItemSkin.java | 1 + HMCL/src/main/resources/assets/css/root.css | 15 +++++++-- .../hmcl/game/DefaultGameRepository.java | 19 ++++++++++++ .../hmcl/mod/MinecraftInstanceTask.java | 8 +++-- .../hmcl/mod/ModpackConfiguration.java | 26 +++++++++++++--- .../hmcl/mod/curse/CurseInstallTask.java | 2 +- .../multimc/MultiMCModpackInstallTask.java | 2 +- .../server/ServerModpackCompletionTask.java | 2 +- .../server/ServerModpackLocalInstallTask.java | 2 +- .../ServerModpackRemoteInstallTask.java | 2 +- 15 files changed, 119 insertions(+), 17 deletions(-) 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 38e6217b5e..6b8010424e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -77,7 +77,7 @@ public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, St } catch (JsonParseException | IOException ignore) { } dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/minecraft", it -> !"pack.json".equals(it), config)); - dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java index b7af7e002d..2cc9ea024c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java @@ -17,15 +17,19 @@ */ package org.jackhuang.hmcl.ui.construct; +import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.scene.control.Label; +import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; +import org.jackhuang.hmcl.util.StringUtils; public class TwoLineListItem extends VBox { private static final String DEFAULT_STYLE_CLASS = "two-line-list-item"; private final StringProperty title = new SimpleStringProperty(this, "title"); + private final StringProperty tag = new SimpleStringProperty(this, "tag"); private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle"); public TwoLineListItem(String titleString, String subtitleString) { @@ -37,15 +41,28 @@ public TwoLineListItem(String titleString, String subtitleString) { public TwoLineListItem() { setMouseTransparent(true); + + HBox firstLine = new HBox(); + Label lblTitle = new Label(); lblTitle.getStyleClass().add("title"); lblTitle.textProperty().bind(title); + Label lblTag = new Label(); + lblTag.getStyleClass().add("tag"); + lblTag.textProperty().bind(tag); + + lblTag.visibleProperty().bind(Bindings.createBooleanBinding( + () -> StringUtils.isNotBlank(tag.getValue()), + tag)); + + firstLine.getChildren().addAll(lblTitle, lblTag); + Label lblSubtitle = new Label(); lblSubtitle.getStyleClass().add("subtitle"); lblSubtitle.textProperty().bind(subtitle); - getChildren().setAll(lblTitle, lblSubtitle); + getChildren().setAll(firstLine, lblSubtitle); getStyleClass().add(DEFAULT_STYLE_CLASS); } @@ -73,6 +90,18 @@ public void setSubtitle(String subtitle) { this.subtitle.set(subtitle); } + public String getTag() { + return tag.get(); + } + + public StringProperty tagProperty() { + return tag; + } + + public void setTag(String tag) { + this.tag.set(tag); + } + @Override public String toString() { return getTitle(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index 32864df629..b1c42c4d37 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -121,7 +121,7 @@ public LocalModpackPage(WizardController controller) { lblModpackLocation.setText(selectedFile.getAbsolutePath()); if (!name.isPresent()) { - txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion())); + txtModpackName.setText(manifest.getName()); txtModpackName.getValidators().addAll( new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index e84ae018e5..ed8e224fb0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -101,7 +101,7 @@ public RemoteModpackPage(WizardController controller) { lblAuthor.setText(manifest.getAuthor()); if (!name.isPresent()) { - txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion())); + txtModpackName.setText(manifest.getName()); txtModpackName.getValidators().addAll( new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java index 365e1e50e5..51e105bed8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java @@ -27,16 +27,20 @@ import javafx.scene.image.Image; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.game.GameVersion; +import org.jackhuang.hmcl.mod.ModpackConfiguration; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.util.i18n.I18n; +import java.io.IOException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT; import static org.jackhuang.hmcl.util.Lang.handleUncaught; import static org.jackhuang.hmcl.util.Lang.threadPool; +import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -48,6 +52,7 @@ public class GameItem extends Control { private final Profile profile; private final String version; private final StringProperty title = new SimpleStringProperty(); + private final StringProperty tag = new SimpleStringProperty(); private final StringProperty subtitle = new SimpleStringProperty(); private final ObjectProperty image = new SimpleObjectProperty<>(); @@ -75,6 +80,17 @@ public GameItem(Profile profile, String id) { }, Platform::runLater) .exceptionally(handleUncaught); + CompletableFuture.runAsync(() -> { + try { + ModpackConfiguration config = profile.getRepository().readModpackConfiguration(version); + if (config == null) return; + tag.set(config.getVersion()); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to read modpack configuration from ", e); + } + }, Platform::runLater) + .exceptionally(handleUncaught); + title.set(id); image.set(profile.getRepository().getVersionIconImage(version)); } @@ -96,6 +112,10 @@ public StringProperty titleProperty() { return title; } + public StringProperty tagProperty() { + return tag; + } + public StringProperty subtitleProperty() { return subtitle; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItemSkin.java index 2f950dd41b..16638033a8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItemSkin.java @@ -45,6 +45,7 @@ public GameItemSkin(GameItem skinnable) { TwoLineListItem item = new TwoLineListItem(); item.titleProperty().bind(skinnable.titleProperty()); + item.tagProperty().bind(skinnable.tagProperty()); item.subtitleProperty().bind(skinnable.subtitleProperty()); BorderPane.setAlignment(item, Pos.CENTER); center.getChildren().setAll(imageView, item); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index c3fe72dd2f..e4c8ebe67b 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -114,15 +114,26 @@ -fx-padding: 4 0 4 0; } -.two-line-list-item > .title { +.two-line-list-item HBox { + -fx-spacing: 8; + -fx-alignment: center-left; +} + +.two-line-list-item .title { -fx-text-fill: #292929; -fx-font-size: 15px; } -.two-line-list-item > .subtitle { +.two-line-list-item .subtitle { -fx-text-fill: rgba(0, 0, 0, 0.5); } +.two-line-list-item .tag { + -fx-text-fill: -fx-base-color; + -fx-background-color: -fx-base-rippler-color; + -fx-padding: 2; +} + .bubble { -fx-background-color: rgba(0, 0, 0, 0.5); -fx-background-radius: 2px; 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 01a0255e02..926ce7e095 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.VersionJsonSaveTask; import org.jackhuang.hmcl.event.Event; @@ -29,11 +30,13 @@ import org.jackhuang.hmcl.event.RemoveVersionEvent; import org.jackhuang.hmcl.event.RenameVersionEvent; import org.jackhuang.hmcl.mod.ModManager; +import org.jackhuang.hmcl.mod.ModpackConfiguration; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -437,6 +440,22 @@ public File getModpackConfiguration(String version) { return new File(getVersionRoot(version), "modpack.json"); } + /** + * read modpack configuration for a version. + * @param version version installed as modpack + * @param manifest type of ModpackConfiguration + * @return modpack configuration object, or null if this version is not a modpack. + * @throws VersionNotFoundException if version does not exist. + * @throws IOException if an i/o error occurs. + */ + @Nullable + public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { + if (!hasVersion(version)) throw new VersionNotFoundException(version); + File file = getModpackConfiguration(version); + if (!file.exists()) return null; + return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>(){}.getType()); + } + public boolean isModpack(String version) { return getModpackConfiguration(version).exists(); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java index 17caf14cda..b59c0011da 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MinecraftInstanceTask.java @@ -41,14 +41,18 @@ public final class MinecraftInstanceTask extends Task { private final File jsonFile; private final T manifest; private final String type; + private final String name; + private final String version; - public MinecraftInstanceTask(File zipFile, Charset encoding, String subDirectory, T manifest, String type, File jsonFile) { + public MinecraftInstanceTask(File zipFile, Charset encoding, String subDirectory, T manifest, String type, String name, String version, File jsonFile) { this.zipFile = zipFile; this.encoding = encoding; this.subDirectory = FileUtils.normalizePath(subDirectory); this.manifest = manifest; this.jsonFile = jsonFile; this.type = type; + this.name = name; + this.version = version; } @Override @@ -69,6 +73,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO }); } - FileUtils.writeText(jsonFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(manifest, type, overrides))); + FileUtils.writeText(jsonFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(manifest, type, name, version, overrides))); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java index 9e4d597f12..611aeba206 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java @@ -20,6 +20,7 @@ import com.google.gson.JsonParseException; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -30,15 +31,19 @@ public final class ModpackConfiguration implements Validation { private final T manifest; private final String type; + private final String name; + private final String version; private final List overrides; public ModpackConfiguration() { - this(null, null, Collections.emptyList()); + this(null, null, "", null, Collections.emptyList()); } - public ModpackConfiguration(T manifest, String type, List overrides) { + public ModpackConfiguration(T manifest, String type, String name, String version, List overrides) { this.manifest = manifest; this.type = type; + this.name = name; + this.version = version; this.overrides = new ArrayList<>(overrides); } @@ -50,12 +55,25 @@ public String getType() { return type; } + public String getName() { + return name; + } + + @Nullable + public String getVersion() { + return version; + } + public ModpackConfiguration setManifest(T manifest) { - return new ModpackConfiguration<>(manifest, type, overrides); + return new ModpackConfiguration<>(manifest, type, name, version, overrides); } public ModpackConfiguration setOverrides(List overrides) { - return new ModpackConfiguration<>(manifest, type, overrides); + return new ModpackConfiguration<>(manifest, type, name, version, overrides); + } + + public ModpackConfiguration setVersion(String version) { + return new ModpackConfiguration<>(manifest, type, name, version, overrides); } public List getOverrides() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java index 721f25bbf2..7313c833a7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java @@ -107,7 +107,7 @@ public CurseInstallTask(DefaultDependencyManager dependencyManager, File zipFile } this.config = config; dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), manifest.getOverrides(), any -> true, config).withStage("hmcl.modpack")); - dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, manifest.getName(), manifest.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download")); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 4a08b2fe37..1918d0fb2b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -131,7 +131,7 @@ else if (Files.exists(fs.getPath("/" + manifest.getName() + "/minecraft"))) dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", any -> true, config).withStage("hmcl.modpack")); } - dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, manifest.getName(), null, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java index b4d45f9824..7a50232912 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java @@ -158,6 +158,6 @@ public boolean doPostExecute() { public void postExecute() throws Exception { if (manifest == null || StringUtils.isBlank(manifest.getManifest().getFileApi())) return; File manifestFile = repository.getModpackConfiguration(version); - FileUtils.writeText(manifestFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(remoteManifest, this.manifest.getType(), remoteManifest.getFiles()))); + FileUtils.writeText(manifestFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(remoteManifest, this.manifest.getType(), this.manifest.getName(), this.manifest.getVersion(), remoteManifest.getFiles()))); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java index 8eefe29e36..8406c9fbc4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java @@ -82,7 +82,7 @@ public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, } catch (JsonParseException | IOException ignore) { } dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/overrides", any -> true, config).withStage("hmcl.modpack")); - dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); + dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack")); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java index 547118643e..0b7e652d59 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java @@ -88,7 +88,7 @@ public List> getDependencies() { @Override public void execute() throws Exception { - dependencies.add(new ServerModpackCompletionTask(dependency, name, new ModpackConfiguration<>(manifest, MODPACK_TYPE, Collections.emptyList()))); + dependencies.add(new ServerModpackCompletionTask(dependency, name, new ModpackConfiguration<>(manifest, MODPACK_TYPE, manifest.getName(), manifest.getVersion(), Collections.emptyList()))); } public static final String MODPACK_TYPE = "Server"; From 85c01cde0076298efdb48835e46a3536da23acdf Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 15:30:47 +0800 Subject: [PATCH 0404/2639] fix: #747 --- .../org/jackhuang/hmcl/game/ModpackHelper.java | 14 ++++++++++++++ .../ui/download/ModpackInstallWizardProvider.java | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index 59817058d7..119b5a8cf9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -157,6 +157,15 @@ else if (modpack.getManifest() instanceof ServerModpackManifest) else throw new IllegalArgumentException("Unrecognized modpack: " + modpack.getManifest()); } + public static Task getUpdateTask(Profile profile, ServerModpackManifest manifest, Charset charset, String name, ModpackConfiguration configuration) throws UnsupportedModpackException { + switch (configuration.getType()) { + case ServerModpackRemoteInstallTask.MODPACK_TYPE: + return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)); + default: + throw new UnsupportedModpackException(); + } + } + public static Task getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException { Modpack modpack = ModpackHelper.readModpackManifest(zipFile.toPath(), charset); @@ -176,6 +185,11 @@ public static Task getUpdateTask(Profile profile, File zipFile, Charset ch throw new MismatchedModpackTypeException(HMCLModpackInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest())); return new ModpackUpdateTask(profile.getRepository(), name, new HMCLModpackInstallTask(profile, zipFile, modpack, name)); + case ServerModpackLocalInstallTask.MODPACK_TYPE: + if (!(modpack.getManifest() instanceof ServerModpackManifest)) + throw new MismatchedModpackTypeException(ServerModpackLocalInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest())); + + return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackLocalInstallTask(profile.getDependency(), zipFile, modpack, (ServerModpackManifest) modpack.getManifest(), name)); default: throw new UnsupportedModpackException(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index fdee06d604..503ffdba9d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -85,7 +85,11 @@ private Task finishModpackInstallingAsync(Map settings) { return null; } try { - return ModpackHelper.getUpdateTask(profile, selected, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name))); + if (serverModpackManifest != null) { + return ModpackHelper.getUpdateTask(profile, serverModpackManifest, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name))); + } else { + return ModpackHelper.getUpdateTask(profile, selected, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name))); + } } catch (UnsupportedModpackException e) { Controllers.dialog(i18n("modpack.unsupported"), i18n("message.error"), MessageType.ERROR); } catch (MismatchedModpackTypeException e) { From 55d78aeba7accf65f62d5d7a2b2cf11d2530db13 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 15:41:11 +0800 Subject: [PATCH 0405/2639] fix: #742 --- HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java index 2d2558947b..f4f6e7bc83 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java @@ -282,7 +282,12 @@ protected Skin(RootPage control) { } // ==== Accounts ==== + + private boolean checkedAccont = false; + public void checkAccount() { + if (checkedAccont) return; + checkedAccont = true; if (Accounts.getAccounts().isEmpty()) Platform.runLater(this::addNewAccount); } From 00c350cd82e379b3783a90fa04db98df14acb411 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 19 Jul 2020 16:36:24 +0800 Subject: [PATCH 0406/2639] fix: #737 --- .../java/org/jackhuang/hmcl/Launcher.java | 2 ++ .../jackhuang/hmcl/setting/ConfigHolder.java | 25 ++++++++++++++++++- 2 files changed, 26 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 1158b2e1b0..01c7a9866f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -40,6 +40,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.Logging.LOG; @@ -55,6 +56,7 @@ public void start(Stage primaryStage) { try { ConfigHolder.init(); } catch (IOException e) { + LOG.log(Level.SEVERE, "Failed to load config", e); Main.showErrorAndExit(i18n("fatal.config_loading_failure", Paths.get("").toAbsolutePath().normalize())); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java index 688d05d752..47459dbf18 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java @@ -62,6 +62,9 @@ public synchronized static void init() throws IOException { } configLocation = locateConfig(); + + LOG.log(Level.INFO, "Config location: " + configLocation); + configInstance = loadConfig(); configInstance.addListener(source -> markConfigDirty()); @@ -88,6 +91,26 @@ public synchronized static void init() throws IOException { } private static Path locateConfig() { + Path exePath = Paths.get(""); + try { + Path jarPath = Paths.get(ConfigHolder.class.getProtectionDomain().getCodeSource().getLocation() + .toURI()).toAbsolutePath(); + if (Files.isRegularFile(jarPath)) { + jarPath = jarPath.getParent(); + exePath = jarPath; + + Path config = jarPath.resolve(CONFIG_FILENAME); + if (Files.isRegularFile(config)) + return config; + + Path dotConfig = jarPath.resolve(CONFIG_FILENAME_LINUX); + if (Files.isRegularFile(dotConfig)) + return dotConfig; + } + + } catch (Throwable ignore) { + } + Path config = Paths.get(CONFIG_FILENAME); if (Files.isRegularFile(config)) return config; @@ -97,7 +120,7 @@ private static Path locateConfig() { return dotConfig; // create new - return OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS ? config : dotConfig; + return exePath.resolve(OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS ? CONFIG_FILENAME : CONFIG_FILENAME_LINUX); } private static Config loadConfig() throws IOException { From ec56e24b7ea5f89e91f3a6a15537e2cec375be75 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 20 Jul 2020 16:17:31 +0800 Subject: [PATCH 0407/2639] fix #717 --- HMCL/build.gradle | 21 ++++++++++++++++++++- lib/JFoenix.jar | Bin 589462 -> 600215 bytes 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/HMCL/build.gradle b/HMCL/build.gradle index 917cf3bfa8..7387352f5c 100644 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -86,7 +86,26 @@ jar { attributes 'Created-By': 'Copyright(c) 2013-2020 huangyuhui.', 'Main-Class': mainClassName, 'Multi-Release': 'true', - 'Implementation-Version': version + 'Implementation-Version': version, + 'Add-Opens': [ + 'java.base/java.lang.reflect', + 'javafx.graphics/javafx.css', + 'javafx.base/com.sun.javafx.runtime', + 'javafx.controls/com.sun.javafx.scene.control.behavior', + 'javafx.controls/javafx.scene.control.skin', + 'javafx.controls/com.sun.javafx.scene.control', + 'javafx.base/com.sun.javafx.binding', + 'javafx.base/com.sun.javafx.event', + 'javafx.graphics/com.sun.javafx.stage' + ].join(" "), + 'Add-Exports': [ + 'javafx.controls/com.sun.javafx.scene.control.behavior', + 'javafx.controls/javafx.scene.control.skin', + 'javafx.controls/com.sun.javafx.scene.control', + 'javafx.base/com.sun.javafx.binding', + 'javafx.graphics/com.sun.javafx.stage', + 'javafx.base/com.sun.javafx.event' + ].join(" ") } finalizedBy shadowJar } diff --git a/lib/JFoenix.jar b/lib/JFoenix.jar index 1672f1ebed5a34b230400c8d57875d659f877aca..290595346f5d0e8d1b3a242b8c65a6b1a6d13ed7 100644 GIT binary patch delta 16845 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 P<=Qz4io`7RZHfN}*>{JY delta 7365 zcmZWucR*9u8YkywoC_F27=b_n2wDvy!wFh(ytZyp>u8K+(EUeBZezxgnTTQmZ%&liN}Q95RX)#S?ZNz(fmar~uDSv@Rqt zFh&C5&~goRhus09nfzp9ssqH& zGi@yms`G*UNajDbxiu@xDwWuOT(PNhNI)6$HdEnbZ70y!@*m^4Q=qbq#*93=+P z8+1XK>sb?LCIpF{$<$y8SSK`~a4?OU*+?@v+t|+fLu9%=-ojvvmk@22JYjYw)$^&U znKYmY58Ne0{1LuGs2E53d;&d_XmeQB6eq_JItUHJ0X;iOwDm;12P|VLFAu}{$~rT)BfJX3 zsS3I>&=khbrCNwzZ(r7T$yDc#jUfGPoD-hFTrt+Pk3Hd8O7elL&9W_060vYT3W_0~d$ znJu{iN-;xNS;DPr`xxNNMjGg=w6DTN=TgzG)d&}t;gcprg62Cwrn{j0G z1g>l}iDqf6^|-rZ6`v(?eVqvp6Skc@B<`jv=#@(S$&o3NW<8`c^47q)&E&*XKEmFp zJSFRA2FI`qW^fbsZX=%Z^fXM_G>b>Hb#ZGlX|bJ<8rVW!EVUC-+xkLAI*xn3oQK1X ztbTXaO z*wcZWzQkzldPdikyW6%gEi+L&wn5VDEv|!AjP1IKv4ct9E#SGH_9yAv7&h1Ruax|@ z^=Lh_i%W9XN|Jg5N^gFWB-XX@q|Y9hvjIaY_rk3WbP(B+$8ddn`?*8XM%=Is`>{{# z&1WGSk63k6{XoA7TjdJ7Hp4)6?fZ*#y?GP%Q|hnm+PZeI5rQ|PR{e*B6UOVU9>X=T z(9Pb6*3Foc>7-qSlFc-lG&wCrirPXuke)?0%^!Ab!AK*{%U+s=-WC^a*b~NP(I^sm z1#xpWs}62wVemyaknjWFt#}Ns+=h&;)Cga0#Yp-)4D=;|W!9tF2GDLpuBUWu^_Z`Q zehe?RV=ZJcTxiE$P|dL69vh2(3yj;2xZVRB_OeDTs0%%IU>5&u$1GA`+XaZ-fdyJn zWy4xnw}W;irv+HCpR!0=@Y+ec5u>|ISc9_yS$G}X*ob$aUv}aF@9V|o?%8f^Cjz0) zE@V?|?9yx>=(G#-xmiP4E3*CJ03%Bc(pY%63+or`Cj*T&XpcAa%b_}J>|VziTyf7>?n}$T!WXrYfyNqe)eDlYQg415 z8s(zdKi*0A2iHLcdC4?No290-jVA^Ei28`Z=o7(SprwQjbkX;m#&M18N z7E~R<6TO+$d;L$`u!^&nMkJDs2xOTC&AH#8X*UJWXcytW2d$x-+ zm7R${WEW!XNBn`tZ*yhZ6*m2WnJf25OiBW=wTKV)7ioW(v3rYbWaj|Tn0h4vr~_DszQ@fvegZIui{G-{S(6_oww0b2!)UT#Etv!1(~T2`x)bX zNoFFzUxBxHY2!vrb(&zs71>n}(obR`gxfOX2jmnUjqryuV}Nm|(3AT@X0&i%C2@nI zQ&{%c*A8@80c}bSS8*o$H16H<0!-^owF4s^5Z!59QA+~3XR&UQvF2=i!?futS?fl2 z;=NKfHa&w8tK4KJpmsTr?{r%2Gf!@Pypz;{ZRNPhFaB^cgoZOi00bQ;9?+!_*VLgM zXX39D6YC2Lx!6Hw)bO^Denc94;>>u}PGd{7wayF?9zMHp^)FHR46L<0Ev zdHvKWr~3V5g9c`w#qu|v#F){f%@^#mIba#1N!PC!XjXgbGv{#X`QI=t1l-Q!=x*OL zV1$lgLLIh79ZYW^I3B$%_-M`ygJT5g>(2l;&SQ`#%N%HF=UgM5#u zC#Sg$_~6XO_9(_TWK7QH+I11<9GvT**?Y_OnBiZHhDCd1Ll1H=PX;yLmO7|l#w~|r zO@v05u$XsFa3<;smRCCOIhW8FQ{X^LwK88udTyZuZO=ppiCA{B_z?sMJa*0FGRz&4hJ& z2^m3mgT@L~J~c=K)w#Ik(zous8`LP=47Z7A=Z&vazPOJoYRV(B5rC`V{?a{#hAi}H>pJkXK%M7GfjtEcjyQbHiLaOfohY|9S;AE%Sb83jlA3NP^II2<=5}HE2+NH4`$!RT#tS4z+kQ>_^iIukOd26gPEnH zgLh?E%0&FxkIY{RNoDwivQPT-g=~w`2P(=i4{_#053oL|8#%qDtum0& z7DBTa(-1b6~dNUI#%G}>rsw$zk@Q} zha~00^$Ohe$K@D4PXZCl8$)LN&Xfq)%0Sx_3=AS|3*qb|oGIZE+P{!MT}Xd~3+!3U zl-^|UW%gMYIzGlPt9#cOz#lpu23BI9XkIeVn^;9S`W%x< zyn{`daR9r*{|S0`xYec;pU~E1icf8NS}r!`v^-q@vnROFOtZ7W9b%ti+AllEbcpnd zneqZ(m^$5YYKEzw$fggZ8<1oQ{RhKpyU0=<$Ts1vg8iZ;=`)zVbST$z{=uy+A0`8L z@P3AcYCn=QL!Z$uWaU^{c7wCeuu8@ijA;as&(YiYM-G-Uuq}mwLFCufoGfgn(m-ns z{{Hu}h03w_!%~?c+*+hlvtQIK#B(nr{2<{a^sX!#0rGnB}T8P>hR$YHl-#sF2XFw0)0GUE#aU*o8e6ebhV07G(AUXZv^ zMIrw+4jt_+)BX_n2APWn8}kNxA~Qgi^>F$PMjmcE#Ya`)sK^ipI=Kps+Az)( zR^g8dll#lED+JV|t~I;W?JX7|WenGo-eOC|f62j;cX+_bBh%$(fu^Y9Gk2 zYwM|Pz0{7ITfCQ>3VW#yP{DTp+MJc-u zU3Ex|CN0aPYe-h(-ZWI8bLxH0OixyOvByu|(~FoSmNO{=4BxBkKtQQYdcvfF=Uj>- zVl&~Aw+4LG|-glW+=NDH%1>sxSU>p))I9vX`OAoYo=%%A2p6&s^;ev?&bGr5(j=JLixguO~K!^q(vs}d?!Z=a7 z2!au5*ziNyH%IW#8YOhwN?nC^{uJ72MSqBJ!?54jQIVVI0dw7OXBP(83`oTbPlIca z8kV_>uJG;*IeR17h>8`NY{$(g{vJYob?d>ph}Bt(RY%N2|n^b)SaVnNb?Y* z1#=fk8z@wCl`g_zfDY-K-6dp!{W>h*;{Foyg9XntKH%?(QPKz4sKK6CjNOB6Xy+SE lAT#Ko)DttiGK_*kFGhK*)a-$Bykfj!)ORi}#;+-&{{h_J&oTf2 From 51325d2423c18317f60e9d892ffdd9542cda1e90 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 20 Jul 2020 22:34:28 +0800 Subject: [PATCH 0408/2639] chore: recompile JFoenix.jar --- lib/JFoenix.jar | Bin 600215 -> 600195 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/JFoenix.jar b/lib/JFoenix.jar index 290595346f5d0e8d1b3a242b8c65a6b1a6d13ed7..2ceaad0b218bc0351567ebb2eb9c43659c8f96cd 100644 GIT binary patch delta 25142 zcmaJp30zE3_s!P4Y2WvK*P@+7k%&qgMMw&55=DiQ5z5+5S0Y6!(xNa)t0WaFTc}jB zg%U!v{qLPOjmh_Y|M~s6y?fSs&fVU9_Z-lscA!no&)J?t7USZ=xVVJZxH)if{K)X{ zjoX6s|6+*#gTcqb*zCK_XKTPN4$Oafi36q6m<&h|!zjS&G$xsJp^hL{>PMh+OZ|7@ zvRvS57A8+&3NKZ`90(9UnC3u&MHOEoDh>-#BSki7gU@uw}u61$;6~n%$()G z0vVb_sj6ilB1o7Y3kz^O3rf_t8bVb{)=LnTzl}bW53AjCQD#rcgk$C4^*ox=6{3(jzf~C$|x=?dxZhM3Z!uDSX@psr-MC}&g zNd6z5km3U8E@3h(p`CkaWJz3Mk$-xFc#7cxssE;U%8UaVQvanv%)XZ5-7K3Tcu?Sf zBBVAD5rQa7f!+iBNc}G{;exR6J=u?p=?rWzSb%fOU;!)&pwY*3RjB`A*_lN;|5d@Q zMW#4=;9LkTW^zD0CB8_!bfBn)^e+$O1sTwqLEr}Cg&2(lM-SjFf^H8JCJVCbsilh7 zgpi&FH;Bj)6%eCz*-e57ta5C=PlHvS#gM3h4=195v&EQX>BgtCAQ8BQK#~yzDO5{M zk?jx#`#LbJbfEnQ;@S7|JaS#^tG%eT9akZ1h4=cX%JHKOl2%j#s|p9cqpI^?zf)mV zU@5FB`dyEl9X8oU#3PFsa%tP=(9A;jJmFfHh8C%CLom>&mcl%S~9hXcIvXk=LMyW4;7gBqMh- zL6s?MD*<(8#-$K~4tjnXM$kg##BPEcV(%J7C`YAWG{F$nTg4FWh(Tt$m5`a@X~JPt znU_JJa>KGXo8XR+X?cW2aqm_d?4U~-_sGOf_zWK0hQKNwVzMZ#bWtF#MCQ%YC9Xgm#`K9!s9a`DG(lzb zEFx3En{$Xik^EvyB0nE2tL%t}kR8|Fh0NAF5Vs<`J#->kz)r~ETTNVmh#fqLXlezm z4X{&a<3SWr6KU`xmKcM4ADPTllR-L3Jb>^H z0pdKQQO13!cGqd58WKayAX=fy;0LgBT^3OqRqo7Y>dvUoC5|8~RuvFuO2cyCE>Tee zmi%4BWW+JEn}}w3pwJ45dHaZG5%HyW!~;kjy+Pt_WVNAhM5+`-I^M?e8eN=3Wf<_1 z+7Sy(fW(hjcs_zG^o2oCa!4+K?KV#%FDFi9himDs4q4>;p5}9$Xkfe^7)?X#P z5r^gF24-U!wM`_nVl(U>kT5jaC3Qp1wmc;fQRTLFQY13Mrw)>-3@nv@l1x$4CVL=K z@CeBp^@c~|B!2ux(CCF8%!xu=A$59KvzJV>gBS#*Db*1v;8UzbfBugTVkE@c2 z=s7_RuXomfH2{lgIwo;wu7r^vU8Z&71VeUy&i=KR^|p8j-u< z-=E;$jEBbL8f3YIS!6S$Or1(F85O zFmcAZ)i{}l2j!pwMC*;9@FA@RqbO*FWXSEKh^WC*Kbt~8lYwC|Wh;VbmQtEv3FvRJY*HKyJBX#a)S}i~Y9T3W#yma_$_2x73Y$0J`g>GEJJ{IdZAx8&N~#&P1eV|vHza>ye2G^b(+GC7ahhnn5zMKwdsmh+*8!u=~FDU^C1 zHQ!_p^BIg|kTT4JA`bS(QE7~xW7KV^pE}1;)dl{?a1jE83slzb7!1;2tE$tfI*93~ z^Hf`;&KVw9>3ES^A^0CtjP!M?Dr<;ZU#FrSD@fvn*g*`cBeGsa1yvO3-&#d=M%GiV zr)r}fI>86^L`*1Hc_CJ3d~eWcC+X9Q^&W5Zi&44M=2r>Ys+@2SU;Q*%|%k zWrqe|UK|#?TItz3+TicKfL|2zW*L}`4WdNhPWg-|Mj{aAgG@2Zp6=q{bbEnNly%n0 zqkCu{t+pvFIKn?$^!O3wk)%uoC8-4a)!w!NjW@LB+v}h9e=Rt)M0)2DVO6z3Z(qM} zuhKzULQDHju0zjDgb#QtXDlRYD9_#W>;BhM-8&0!Sr6Kfzb_q8G1ri~xV_;vk9VX% z`Ov&qey@&v`ev|Ysq|7=i7oVk8+KZ$r+4`4B;Wqh-XtIAZm%52r+n%9r!6Ae7rvcc zZjo3^`V>*I((~o@MAgsbwfCf7Q93189QyIx?6py-%nFd8Dm?POQ+9{#;r0U=k6KJ( zT8cC-%mhINR`-rkMh}*%=S-U3C_5xmyOko^|7}H^eS7B>?+4o`?34EC(wt~D9<9CB`Il$8KCG-QcN==+<1;CJDZQyrP|t#-CiY;F zP0+bw!}PM>cyEQ)$GGgGhn+PxufdK13kl4D9soc|OXMhN%6^C!`ER_ z=gsC(%P*r9&6U4LyVp;01q;o;lxJPJKQY$LU&z1mvi^q=fjPf*n9Wv6eAAJT&yX+C3{OqAid_1v9!2sv2C627UhvEy=P65 zQwL=(xzwfaSWaxPKdC;i{hD87uFXoV{mLv`aeIijwt(uVsqLdvi7FU(?gdN4cu;u6?iNc686`b z>2&|*!?3gOwCIPEI$z(-eBjR-L~t2!!xQ7O%=o+BEt` zSXZRL%k|NX^?ybW)_7%axb^6BlY!e;hkC-ii#?gK)@HiJ*LNwktgY#j?s8nstru7< z_kPVRJs~~gt1o-wg(vd_+j4s`cYVEpc8^vI)oRmwolgSGm(%UP9OzSAQoUbPhC4X< z$L|Hpmpzbv?C9`u>)v%edmOAuv4PL5xK_0`-Z9rJE>NTEHlKQ0u&3%=d6LPa5^pWD z6%wZmHIp13{^rjLwviY}jP*WVy#AzE0o^V$*Y3f}eCNrsa{(J=?)v0hcTTG|?=iR; zfF97pIvWV7F+jJcitgCQ;(X(Jb&~GOOJYqyQMsOHiN&V z@!l+9qn0a2b#|?+{Z33DbfBw-HtpJBQ{`tTn_QyTHsXA+%kX}Omrb4SJO2~uK84|W z@AuqY>bvgoE$R8qp|hk-E=V2STiyKlVt!dp%_9TB$T@o{H}@P?&n>K@XMQ(tUGC_T zR+Ds(r0O={zN|<7*O%-#rR^6=y~+yHjNV*)-598;Q+#oa>ciY6p@+%*W;32GYCaqw zyYa>EfV#7-#0Z9xX^Q; zCf*(D#JM}Nv}+G$$t`djH; zp4GiWb0+nJZ=Ai*Q>Gm*`Py$U=J89=zE|QPUF&=k!#8-|LYLhhqZGT(k|u|?yWd)V zId0#lR<(0$&e&hl$;;L7T5{#q#Lg}EvZAi|(Gq@!hO7j2KkKh{3spYfA-RtJ=jCiK zRr47-VTGD1W~dNB5KzpTeaQAx3kivGEOk`sP!-*@xCsYf!VsdaYIxVk5ZeXCa?zbopt5e?ktBC<|Bv3_5lXp%+(!Oo4df$#czabI2aff4 zZnE>(a4ly@!B2UxvgM>8?^{3W%k!@VPOSIlvNyPNsI*vguggbpGS&K>!0BzOCb|WJ zSqE`f`#4T14T&w}L!oLotUZ>WZL7ADay_~!j-~*Fm6-3A5%^}Er}@jb$y<$&3-i0kw+pFysk<2q2%boMcciwtVvwi9 z@aLUqb-Th#Z*q!1-uA^-9lX`(^Fo9#GOjr>aJ6BH#LhFzjwyY4Nzb{m>80y(J&_d( z`KsPxWnDvQw2gf2rk$;Z@#!ZH#OIC4nGM*+-%#_a6I+?)eSYl~skVr<4f4x`tSVeZ z!hrXsAC8e3Cn}a+cDSDrxaMxO=7HlvT>ZODRdg3-=7v_pn$_{IbzOGI%Qydx)tj;F z!=k^2&ip>#L!LafHp3wNC_TP7VO)wrKi4m#>2}zQyHrNR{N0dw-9YoUhE}I#hFdgu zRK73X-C`f8aY4D!AVN57{7#EZG@tT=;!|&zYtJ5h|0v|OUTEjBTW*h!%yoOa`fXX! zinl+?6M2O@>!SF1&G{;76F(gOF|X;n%JH;Rb?weI{KSG4aw3*?;d)i$+Vrddb>qaX z*XNv{JJU$FqWpKbTUWlHtfq2Bz0moC)P>d8U$uRmso?Bwdf5B<$CtWu>#aYQ3Jj!d zUiE0mvMzMVzJgP+#m5Cru6!5~QgnIvvibDpJ3sS6{-j(Y)-70h($*x|_~Ne5PmkVy zwM{E-=gj{4%(95WetZ9${)YR79;S=a8`rhuLmbaN7 z)zG-*cxR_timpO(+7~5TKhki1?)xwE>-2hNXz1&zMt`3xbzAINz|%wgkMok_O zFrIGQma}%Fz2B};r;1;1N7%Ed?Mu2de$cu)=qf;jC-3yiCkP#6fQ11pe%-|fmTVHU`mCM z3|OXu@zU)HtI2P3C{}h>D|_q94w7YDH&h;+RpG?2o?Cq14^Gw z(-N|`fBRE*g%Jinik0fu2P7Tm8<$;fTiR#<^g@R#>A^d|PdzoM?X#CWf0uRmx#&_u zz9FU7+z$SY*Gdw7PyIer^IkEu&TMgA<%M4!N5o2a^P z=WG@1tVKu#4O_S6=)Up|=U_Ox+y9$(ii>o)Row=SK;i?fco zYW`VjHagEggkEmjS$itxtI6PNg#(Wb^OqhdK6YOPeON|-A3WnvA^SKlX2VIJl6iH%G*w->j+%44!JjC6dAO_ z-n1ze*f##WJLsvrUHZ?r@`c(0lG!5LWE*^hPpB+0cU`>NtdBdW0MK*QmdoiZfSOWN%E5#+u!DN zb#44z<>5zWHd|*!^|{9fti1Qba3xJtcpy<-MW!)IqonB6h|W zzTCECnQ}~k*|ks9j_Vs19UG%%-2MJiaeCh@8G81N)(1Q03_&igMeNS0O24=&V6EsX zvAsn~qPH{6%AQcH7B3@;)IWQ9ce(OD8x`$zxH*}}xMJO0(1-o1)U{dMMh##~MM!D7;kBdL-Tot`>+8)=>V6~p8^2e1uU%Ev9}Kd>l15jB=6h|AO`|W@ z-Sl$JvK)u5@5{wyORECik6qGE+EpL#UGP$8-khRa>gktOey+EqjJnCy81sE~c2%Kz zx*eUX{ra3i*=jGdLOYn(a_q>RUu~^=cdP89c zS8cm3!e^AMMXv5o;X8DDvuT~=jPJK^&k&~@23T!g$}8hylyzQ_bZ4f;x%crc!G$F% z#?e0gbB7h42&NOtn^=|aMvH~uc?=MK*o_5-A#=1k@a0L z=l#%EtrxPWOJ7P?|?$g)Q&o#QkSeklQ zNSUcr{o;yjFZcT9vPA{*JYjXs7X%*hJ$`ene2$8IT#Dk$3c37_IXmnR=9HvvpS{9I zOT1Rg`rvlWIa(2WmereS99F$3XT0fS_`r`&Bhx)g>52{cF^epU^6vF$KW!HMQT|o! z2TwJolYYod)GF0mDSKAfWut>Ltge1CdN$d7Zn&Q76{M9UXcn^^@!v zec~=(OV;-pw`x>R`8~Jyk<*u|%8R_aow)vt)~=XdfB$#yMozD<^6tZbNboJh}vfQ4zo3mn*b9xSa zd+NUSMAZRx@6-2wJ~9zBu@WuSs0`R(m(p@-&yDCKbI$DzThq0u^u+wLALx_(x>+;U zOBYJZ(51o zy(%_dr~5By{BfGUNUkj5ak|9$N8{f6!^F=>2xJ|!M*OUw>91Aewi`C7eMay z^yL3;Wb2t@e*V02v$^Jn8IC9JeA#u@`_^sY?N1i_wyV8(_O*~}k;s>}SGgl{>w9Hq zG!N-jH6)mg{Ie)1QI!C%4(3LevUsf0QApXu>nRjwm3dJq|7(5O^E)O=YT}|Vhts_0 z22oSfe0TDWuRgs?+494!`As81%@>pQTYmPavgn@E9kh3RVuDnoQ(=&_;8D#|ZiYcq zacE7#?hBs|W;oyedhIB2U~X@gtK;fe7l)%MJnN)v+Ak)%Bzaq|SNOO?U?-pl&d8Rs zk*TsY^fJ=*EOJS)deS?gVdb#Nz}IWu0a~ZBrjz0vD!<-|&*l{mJCd-4eydFO^e$eW zuh+|1T$8x@!B4+M1j+~beac2pnB_v|+tcc9N0Gq3yXz@stP7ag6(r?4T_`(1>Vb#k(g*1P6O z>AS19N?z}73+t8Hbw9E4#ETCR=jDM3CB4_-h|WdT^vDd%I#S%JQlocMJ&6(3fQjmZk}#4>)hCRgd7?xc4-?!<@=cX$4lrAMv` zqWn4dWd(sc%7}`&chOeYswedqkU5tVDgj+u1u zahobDxX1R775_0h?xr#*U-f>#`0S&IA3qi(D*hDokL`LLT&uIKsOY}e%23UrJ2}T^ zXi|j(4TazNyNV9qyOi;@_|Xh2zlgWj-qSz)6j805d~v&JcJcm`#e6zZM?2OV{J!)) zH8)Joc1^>*2WqE7bbtBtyeZ%BcKgmE*-b}|Xz-rvA3YkW*!(Qz&pncEKXIoiq| zow?gIr{w5bhusV3oj>UPVZl;w0coD!bUUXA$@hl?wZ#i<42}y^3lF*M;=7f#nLF;Z z$_xdf!q>IdM;zCM(L16Sbs2AQ-P@aUMPS0C3&_3E&7#N5Ulwavn`qqaDmTLSd;X%T z)|okmeO}M%~jMaj{7&sGU1JFb18tv=&uZKZR8 zTK2{^OWj`qf5JPcf#JK1!XuigVf1Tt&K=<9%w^}3^8MQ~#or1@%o}XXU z?^NaW(Xd|s#ZxDj3lamh^-{ixrL&u7f!Zd`sjoh)ml+AS9cRrzg+8{NzIIiIjnISy zcH4&B&?&P}RMYH85VqM`KVWe{ZFJ8a^3h9?+ge_FZi%k=))u2tomcc=j-JE!){6IV zgBZGUR&87yZ&XsapI=qlZ{KSdR?(|RL~AU@q!ugwG3EPEw$Cbd*mC}xNGHA`-E4!V z_~CU8vnojTG9860!eZVRY-i9HM8?*t+pn20s(avCmA^VYCT-?ssSO4bvhy`{R;G=C=vZA8{%<(Asw$IBiR-@GET8jf!I3k|K2 zLiK##Lw4m38yccGob=dwGM{s}1);K*nw=EC-bXo=kI3^{7gCfrNu`#0*flt5saWWT*sXgf zy7$315zhy-&vpy@+jm`1ezQ>Qd)WnVt3%N{rIObj*gNpG%(yQ#=$JNR)xzAs!cU1q zR`kn$O9r2LywCl4IrfnUHSyBDs{D<@Uxd>#RKB;}y!W}@r`+tg;80d%Bm)3S5-#uX!`xv%2{R21tq z6at?=x*FFay*0Fx@Y`T}Nl#?OvWVhkyeyzIvea#kg|5x&!MqkXRRu^^-O!$@D`^Y0fAKi+ZTe(3%qN%TfdcMW4o;`vfS#HX~I zbM=Fz&2D#SrnYIA#Tp)Qg6AMDOCu@ydcOkITx5Vz^>S=U*@V4iMn+`(O_0sSr@X%- zJ6Pn7iEW|KXTFka7j(DF1n~7(TA3>ET+^HB@iZERl9S904533Xa0?0gCc>z$pmwy+oP|r6B3D=-)6ae-Tl?; zcHQ%Q;l5gpyQH>7{E|-g()TvJFb#57<+JnBr<|axVUo>nq*Ld{7_w-*0?X$T? zpO+*pe7R8Lkn|?XW{cgLa|O4)NzrJZZ7$%@V>8?C)~XWmM8Ex3>(3=`S)r9^;ku@N z3Gw9ijT?I0?_Z@K&+`m;=q<5B;_yT_PG~K9(n{hn$$9Y@I5G?4D1}Xv&zsi2 z5V^N2$6=m>b%43-@LDke7vj&0(g!Wi=H1a6@7b(>X0j2D3+y30)^RF zJN%^ob2i4{W__2Jn)-?lDl9Q`{8KXMm4n~R)`u<)ELev1q013!E3j3Og)jCM-9{+%$4;WkE$Dj7x#6uJP@2Sa->N{W+}2qSGDhAu-e6!&AEh-7aJCW`JfbgD!C z`A4unNZ2wB_)r~(IU`J=1gsL34->HxR7NLbB&0;l35-UebNzEa9d{5H3J<`4LaY)G z79bGCSQP(W>_XuJ_zzL2z<-G1Z}7lhO7_JMh$D(f#L<7uA0l0bq6y@QTw-AUX-tu# z1gq#tnc6@|jz-aB3dfky3@g@#iq7Wd;`$-L#ihffM*k_ne;$OSEJ@IM8k5!dAI+0R zsLUUd*a?KwF;ygSRywB0tpuyYF=m7U*p-fnLqJL}O`6p}1l>r(q1o~@Nd&FpqnWYP!JVgRh_mCHiOEx)?U~&sCB&H11e=U;l(BP|43a37$&zR~ z8wbd%(wKnoDZn9f9FU+&L+(TYAh^+*Ef7EjB$!|#Q__Hb77Mz6J`S0A zL-0;X1I1aGIWmWmwKVTvi;4oF^Oy;eVsoCwXRQt5qmXjeMwl%GMw8$w9J9lL5A6PG z03%CqAq=2=0h@z_C^~Zr5dr%y;KCoeaMss?9u|JcifJZW0irKp8YzV<1i(23W|vF} za^uACa)W~=CEZO@mu2+-8a5=s_7xg9-fL2X!lnLS0=a1fClP_dlnqjP)^KXj!UTex ziH4NREx7LgRejnpZL z;OG?mna>m)bmw4v$Xx>v#++_G1L0iE0#(5f8{A1eTUhAQQ>;>EZsSy5ejA$~mdE6m zLf8(6R32*>4TZ4a!eDbAa}K8@8dMO}r36m50cOnCAGBi>6 zikkv5E@854r8@U=_J&3TG{TL^#fhA~iho8fKqB1{LF(6O1bFX{oq zVrD&xjlu=|d6IIqT^VE-GuK!Y7=_pGZin^rK<4x5Ylh1cRUHS|<&CNTt{JyqLIM+J zm;(?h#hrWPDvO)XD+p8q53k~*4n|brQr^6S^)e~+kMcn2IzD0@KS~475|-2TKC<9y zz_|?P2}7@N+Ry)S9#VFKU$-yp4?Xg(Cm4B8)ZT)a|kqjtCou@z312#e2sN))EC^G#V#nl?K9; z1Vd z#Zm5;Gp9q)U(OPFI0Ogi-@>F3ncXcG;93|CNW6t_%3!b_=kV_Wt+%j+occwD-tzN- z`g#1va5jztZMWdt9*VeQk7pR{$LWf}eYm)q3QP*=0b>9;!Ada*tOOJ*ar45^K-^?+ z(|}7QW{gN;r|J%6pgN6z`W6fvtF!m9bwi*c4;wD{O%i?$P8xXF=G(ci4t{IGk#05S6i39p;@s0(fBBg=iZC1DQ z7{j6EV+0|#nf!0FXmiQHumR2(DAp2CC`9&l0L4<`svHDgZ)1k2;V`0-Q+WdgoOWX! zCWgSf>sU+==^}tEm}x*%W{-Oqe#uGPq0h$AVvlYLDIhVZbM+MhTW|L_RQBk2?eggL2}WwZn0S zU^OUe!Iv-?D2h8m-GL3|0T=J$R)LYDoE!?Am^i7<#J`=EuYtwjlRE+$pmxFlQ%*8n z4+N0`g7@GEWUZ|z_!Ji$v7QapMZ_@t6!#t6E#1QwqbeA1%E_~=qs7w(l2r(sS_9l{#QQ7^YLx~(jVuRO?qH+nvAZUW zcjZ*nJe-ZA4lufSMXPMj-IY#b@kPbsb#0nUNBOa(^6*(aKtYKM1HpaU=%UuB6S}qwctG(h81%Xf9?dzEpU>U z-$j&X4<#6KEDc&(Sp9?E%|_t{V=Wlm$}yvn@z%G!o(>iLt1IVJFX6f*W+9yBjo`VM z+O&2ae#d4&0X^@C+@PfucQg!cmIhy1S!(bN;&|%^iR`yR0OOuHThsE5jY9?WHoRlO zm}q<$wu9m}%o=I`16DEDj`#fFY8zY~ru+^gq;bFxc$n3Onf`4IB7-5*(%{u2mO^^s z2t^t2KE~xpJ!aAVR7C(8uvCro*C8;xnp0C}cshk}JdH?yx1})jS{e*KX7N9*!+|oT zAdJf9WYaSf$JzS?WA0yJur?={&xp-Jjome1AU7wDxhWgxpWP~q^u~=b3m!7Dl*K@z zIf`g=5r>WrV&PJpG-RHRDU=%v1n#VWcI55DRW8L(FuBmy>a!rRH z2g+1SmIXqTnJ-u0>km8!M;wG(I(>Acxvno0*utho5D!Jp)g>d z`KAYB^`*grE*9;>bR4R5hV*xb1;hC9v7ZLAx-h2kU_EzoIOZkq5)2vrVcg^KS=Ds#{f)1z`0&< zf!ZEy9ufev65x_&jj+kcpr;2TgTxUMe2d}uc!6GveczrKQiO|{IDFIBo$5=>6QQf) zh=FA41W8hd^CXrXdC$U@WK*GYH5t&>iz!Zh?)VpX`gxBN!j%CAuQ48^I?RN?*`_0G zCVKDe{VX`Rr_!{@g?+xgiVFz8UQ9uiU2!P=Go}uf z4&dDa=G2e|>p!z5<&l+a6odcesOjTf*#mS9z=8PXGd>r?6dck(aDc^cB@?R0mbPku z)espkM5YHWvD7G=0(5Ug0JACK|9;$^-b=bSgSJ7~UgtqvI85UK--HKQ!UY2nR0U)V z;*N*OJ#c3ZZbty-2^LK6f!B?O;>a+|2Xn)`c?uA-8v&F-@fUpNg&99M`$`Gu{er*e z!xSK#gU2-J_b{T;3^ngL=;kBsGCfI2Vi7wApI40 zlGaxiif!({D8XOxg$3po;gl|X^fG|o0!~9|mv%qi?>wDlhLXi}qe`X(;CkB437-4C0ErN}x05V7L zaS2n%z}@&1N^KMyMG}mT;3kCGWjN)1p|f!$fX8oq=)uf0oH)d6gd>Ua$B2U9YzhWy ze&h0BY8rT8@|&d+xtNXjcUFX1YdCrBC}rXN!AC1hW`i5YlEEexL5XdcA827t8%|=b zat@rJataj~jN*#S9%Zq)U-1{^znv|ho?kK)y+|5fibx6lcWukB#;IFIF*)RXm^%mW zRsukH44-{q${bFWj42?52yZ9t8^foEv@w<2Sx8md1Pk{!ylaItf`Wzr%Zm*%z{4+F z`yJqs*fIEtX8Prjk$E`rxd}`Sajl=?3ar=w_z7bY?{fTLD4P zV6t!%HvIxi&LKpm2P6-3|2^0EFvT<=35S{!X+p@PFr5+ZyD$(;q%pU%#juKb?9z7~ z;TlZWk9j7B+*X;*NV^Nq#BBNh-Ld|;iz~i{L_^=Q!A=s3q4)zFP)(vSFId4eNw_52 zHwd5tir#Q@gZbz2Q3UfQae7RE2)wvyvOtMKqk%{=)0W@}nZ==l{1^JKMPb4vT#N$z zKFDIhd^LqBm!yF+g@)fWdI&#TvIXp;-~wPaCQc>9_}DoAehY;8nm93QjS!|f(BsA# z!8A^s8-Zl7o}0$H8i8>kd;b2dm=g&5&o~?k(^tTkvvF2kELJcB6z;P)AV{SdArr$C zP@KXa%|jGw;5e1pbwL`HrbtDL=?yO`s69r7$&f;+6yWSb%9jk(`d{qN-*~n z+`7?d+)V9MvVe8v1la~DHT6U93HT5FWt&c&cF}J~xF5`z#JshI@>St} z-gS)RswV$yuZSfR=A$rpoWL0J9YPk{Z`Ao`vSexc?}5j z(PXA=^AXau!ykq2z{_O=(3|>G$}){Aavf19fny9RP4J(ucqlg(uC6MBjRkXJ=HW*F z451Vy$n6*q;-i@%r^CEioXt2_g~+r) z(G1Q&%&Fsne?2<=)gl!1a^U`ZX=VCR!X<<&0~QFs_3t|$%ngPUZ=1lO(jqk3Ijo_;zKzW4RB--h z{m@V-62UmLhT&r%NQ9=iR0%?#aY7xe9BpkDuW+5|V8eOF^DqDDuU%%MKp5T&<;E#M zrYI&QpvEEJp9z-)I-)c!cnP>o94`BTqBH?wIujrZQaJ$65a1CLpbBVWe<^ImAV63Q ziP8lz5CC(e!8MK*y7MsP_2T((Xkl<@&1Zk2KN!pyM(4`>!oldLO`NK8PX1Z}P+ zr@U!N6Q+?g0wGCS*tC|RD0X%b`!wW>YPd@9Qtmu>{TWPXa~K{q{i8M$Aq8D@T_*`! zo+9;6%b7uGphgO|yigD4hVHlGb~2Lw2OE!%S}zT;Q}uCdc-2)LR7(G26K2E%^u`0| zjV04`HZ;NM;JtB4T*?L+n*7x3{lEPT`4|78eoTP(QOeD^^mooqW zXQqS~@PEWMfJvbOoMorpJpYqo#x#mtCWQ|BJf={VH8uxv0GNQ00BC-clw$$9XCu{h zn0LRY8p{p~VDbLDA|S1RC896{`sw&I590;!@&ASeVBG*mu>&|@;R2k3b@>~>@Bz-L zHV5>|)0QEvU_1d%(YusMG40AX3@d<(g92-D&|HS|2Su$q zEFbfF7;YJc6yZ9|wwx0DtJn>fICU2ssRIKRaCLY$O##_gzEJ=J4m=946hV8W1ZlCa zdjlBI0AEm)S-PI|$F-Td?+wEo@JU|>Br4Nvkti7KfOA_7uMr{Za$e>JZYnJ3?qD1` zb&tDY3eW`a5+Smwd)zQSf^*_F+Kq#!Zgc0TvKS`p0R#;=d7!lZ>|P_I#)2N(%Z8Gt zUFn8l7Pz{~`#3OQv;~{T delta 25359 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 {&P2RCatI4U_@BerEm#6IU1)+wpD$I=wCZw5Q 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 From 37c47fc2dc2a8f2a67d2a39164b06724c5ea426f Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sat, 1 Aug 2020 14:47:24 +0800 Subject: [PATCH 0409/2639] fix: #751 --- .../java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 99116b16d2..1bbb5071e3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -81,9 +81,9 @@ public DecoratorSkin(Decorator control) { parent.setPickOnBounds(false); parent.prefHeightProperty().bind(control.prefHeightProperty()); parent.prefWidthProperty().bind(control.prefWidthProperty()); - root.setOnMouseReleased(this::onMouseReleased); - root.setOnMouseDragged(this::onMouseDragged); - root.setOnMouseMoved(this::onMouseMoved); + root.addEventFilter(MouseEvent.MOUSE_RELEASED, this::onMouseReleased); + root.addEventFilter(MouseEvent.MOUSE_DRAGGED, this::onMouseDragged); + root.addEventFilter(MouseEvent.MOUSE_MOVED, this::onMouseMoved); root.getChildren().setAll(parent); From 00b945f6e30eb75441db58f95f613e94abcd8f03 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sat, 1 Aug 2020 15:08:12 +0800 Subject: [PATCH 0410/2639] fix: #746 --- .../authlibinjector/AuthlibInjectorAccount.java | 7 ++++--- .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 13 ++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java index 24cbf504de..14bc95f559 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccount.java @@ -142,17 +142,18 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof AuthlibInjectorAccount)) + if (obj == null || obj.getClass() != AuthlibInjectorAccount.class) return false; AuthlibInjectorAccount another = (AuthlibInjectorAccount) obj; - return super.equals(another) && server.equals(another.server); + return characterUUID.equals(another.characterUUID) && server.equals(another.server); } @Override public String toString() { return new ToStringBuilder(this) + .append("uuid", characterUUID) .append("username", getUsername()) - .append("server", getServer()) + .append("server", getServer().getUrl()) .toString(); } } 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 dbc13a9372..e702868a14 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 @@ -35,9 +35,9 @@ public class YggdrasilAccount extends Account { - private final YggdrasilService service; - private final UUID characterUUID; - private final String username; + protected final YggdrasilService service; + protected final UUID characterUUID; + protected final String username; private boolean authenticated = false; private YggdrasilSession session; @@ -174,9 +174,8 @@ public Map toStorage() { Map storage = new HashMap<>(); storage.put("username", username); storage.putAll(session.toStorage()); - service.getProfileRepository().getImmediately(characterUUID).ifPresent(profile -> { - storage.put("profileProperties", profile.getProperties()); - }); + service.getProfileRepository().getImmediately(characterUUID).ifPresent(profile -> + storage.put("profileProperties", profile.getProperties())); return storage; } @@ -210,7 +209,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof YggdrasilAccount)) + if (obj == null || obj.getClass() != YggdrasilAccount.class) return false; YggdrasilAccount another = (YggdrasilAccount) obj; return characterUUID.equals(another.characterUUID); From ae63b9712e35665051ab0006510ac384de8ebcb8 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 7 Aug 2020 17:23:27 +0800 Subject: [PATCH 0411/2639] Revert "add: accept authlib-injector artifact in current working directory" This reverts commit 02cb2a3fb1fae0488c0b2bd1425effcfba865311. --- .../main/java/org/jackhuang/hmcl/setting/Accounts.java | 8 +------- .../auth/authlibinjector/AuthlibInjectorDownloader.java | 4 ---- 2 files changed, 1 insertion(+), 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 ac89e0f461..4427fb687b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -40,7 +40,6 @@ import org.jackhuang.hmcl.task.Schedulers; import java.io.IOException; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -244,12 +243,7 @@ public static ObjectProperty selectedAccountProperty() { private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() { String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location"); if (authlibinjectorLocation == null) { - Path currentDirectory = Paths.get("."); - Path artifactsDirectory = AuthlibInjectorDownloader.isArtifactsDirectory(currentDirectory) - ? currentDirectory - : Metadata.HMCL_DIRECTORY; - - return new AuthlibInjectorDownloader(artifactsDirectory, DownloadProviders::getDownloadProvider); + return new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider); } else { LOG.info("Using specified authlib-injector: " + authlibinjectorLocation); return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java index 33fe053be8..82953f6622 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java @@ -127,10 +127,6 @@ private Optional getLocalArtifact() { } } - public static boolean isArtifactsDirectory(Path artifactsDirectory) { - return Files.exists(artifactsDirectory.resolve("authlib-injector.jar")); - } - private static class AuthlibInjectorVersionInfo { @SerializedName("build_number") public int buildNumber; From 94b6d7596ec9e2cc3040a387d956d19f784b0701 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sun, 9 Aug 2020 17:02:42 +0800 Subject: [PATCH 0412/2639] Redesign authlib-injector updater The process of searching for authlib-injector.jar has been changed to: 1. use ~/.hmcl/authlib-injector.jar if present 2. use ./authlib-injector.jar if present 3. download if none of above is present Instead of checking for updates when logging in, we now do it at startup. We only check for updates if there is at least one authlib-injector server configured. This changed is expected to imporve launching speed. --- .../org/jackhuang/hmcl/setting/Accounts.java | 34 +++++++++- .../AuthlibInjectorDownloader.java | 62 +++++++++++-------- 2 files changed, 68 insertions(+), 28 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 4427fb687b..34a6801306 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -29,6 +29,7 @@ import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccountFactory; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactInfo; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactProvider; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloader; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; @@ -61,9 +62,22 @@ public final class Accounts { private Accounts() {} + private static final AuthlibInjectorArtifactProvider AUTHLIB_INJECTOR_DOWNLOADER = createAuthlibInjectorArtifactProvider(); + private static void triggerAuthlibInjectorUpdateCheck() { + if (AUTHLIB_INJECTOR_DOWNLOADER instanceof AuthlibInjectorDownloader) { + Schedulers.io().execute(() -> { + try { + ((AuthlibInjectorDownloader) AUTHLIB_INJECTOR_DOWNLOADER).checkUpdate(); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to check update for authlib-injector", e); + } + }); + } + } + public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE; public static final YggdrasilAccountFactory FACTORY_MOJANG = YggdrasilAccountFactory.MOJANG; - public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(createAuthlibInjectorArtifactProvider(), Accounts::getOrCreateAuthlibInjectorServer); + public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER, Accounts::getOrCreateAuthlibInjectorServer); // ==== login type / account factory mapping ==== private static final Map> type2factory = new HashMap<>(); @@ -206,6 +220,10 @@ static void init() { }); } + if (!config().getAuthlibInjectorServers().isEmpty()) { + triggerAuthlibInjectorUpdateCheck(); + } + for (AuthlibInjectorServer server : config().getAuthlibInjectorServers()) { if (selected instanceof AuthlibInjectorAccount && ((AuthlibInjectorAccount) selected).getServer() == server) continue; @@ -243,7 +261,19 @@ public static ObjectProperty selectedAccountProperty() { private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() { String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location"); if (authlibinjectorLocation == null) { - return new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider); + return new AuthlibInjectorDownloader( + Metadata.HMCL_DIRECTORY.resolve("authlib-injector.jar"), + DownloadProviders::getDownloadProvider) { + @Override + public Optional getArtifactInfoImmediately() { + Optional local = super.getArtifactInfoImmediately(); + if (local.isPresent()) { + return local; + } + // search authlib-injector.jar in current directory, it's used as a fallback + return parseArtifact(Paths.get("authlib-injector.jar")); + } + }; } else { LOG.info("Using specified authlib-injector: " + authlibinjectorLocation); return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java index 82953f6622..4961ab716d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java @@ -31,6 +31,7 @@ import java.nio.file.Path; import java.util.Map; import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import java.util.logging.Level; @@ -43,38 +44,31 @@ public class AuthlibInjectorDownloader implements AuthlibInjectorArtifactProvide private final Path artifactLocation; private final Supplier downloadProvider; - /** - * The flag will be reset after application restart. - */ - private boolean updateChecked = false; - /** * @param artifactsDirectory where to save authlib-injector artifacts */ - public AuthlibInjectorDownloader(Path artifactsDirectory, Supplier downloadProvider) { - this.artifactLocation = artifactsDirectory.resolve("authlib-injector.jar"); + public AuthlibInjectorDownloader(Path artifactLocation, Supplier downloadProvider) { + this.artifactLocation = artifactLocation; this.downloadProvider = downloadProvider; } @Override public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException { - synchronized (artifactLocation) { - Optional local = getLocalArtifact(); + Optional cached = getArtifactInfoImmediately(); + if (cached.isPresent()) { + return cached.get(); + } - if (!local.isPresent() || !updateChecked) { - try { - update(local); - updateChecked = true; - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to download authlib-injector", e); - if (!local.isPresent()) { - throw e; - } - LOG.warning("Fallback to use cached artifact: " + local.get()); - } + synchronized (this) { + Optional local = getLocalArtifact(); + if (local.isPresent()) { + return local.get(); } - - return getLocalArtifact().orElseThrow(() -> new IOException("The updated authlib-inejector cannot be recognized")); + LOG.info("No local authlib-injector found, downloading"); + updateChecked.set(true); + update(); + local = getLocalArtifact(); + return local.orElseThrow(() -> new IOException("The downloaded authlib-inejector cannot be recognized")); } } @@ -83,10 +77,22 @@ public Optional getArtifactInfoImmediately() { return getLocalArtifact(); } - private void update(Optional local) throws IOException { - LOG.info("Checking update of authlib-injector"); + private final AtomicBoolean updateChecked = new AtomicBoolean(false); + + public void checkUpdate() throws IOException { + // this method runs only once + if (updateChecked.compareAndSet(false, true)) { + synchronized (this) { + LOG.info("Checking update of authlib-injector"); + update(); + } + } + } + + private void update() throws IOException { AuthlibInjectorVersionInfo latest = getLatestArtifactInfo(); + Optional local = getLocalArtifact(); if (local.isPresent() && local.get().getBuildNumber() >= latest.buildNumber) { return; } @@ -116,11 +122,15 @@ private AuthlibInjectorVersionInfo getLatestArtifactInfo() throws IOException { } private Optional getLocalArtifact() { - if (!Files.isRegularFile(artifactLocation)) { + return parseArtifact(artifactLocation); + } + + protected static Optional parseArtifact(Path path) { + if (!Files.isRegularFile(path)) { return Optional.empty(); } try { - return Optional.of(AuthlibInjectorArtifactInfo.from(artifactLocation)); + return Optional.of(AuthlibInjectorArtifactInfo.from(path)); } catch (IOException e) { LOG.log(Level.WARNING, "Bad authlib-injector artifact", e); return Optional.empty(); From c60261d917eaeaedcf54ed3464a4bf70e91778f9 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 18:29:01 +0800 Subject: [PATCH 0413/2639] fix: #755 --- .../jackhuang/hmcl/game/LauncherHelper.java | 2 +- .../TaskExecutorDialogWizardDisplayer.java | 2 +- .../hmcl/task/AsyncTaskExecutor.java | 15 + .../hmcl/task/CancellableTaskExecutor.java | 304 ------------------ .../org/jackhuang/hmcl/task/FetchTask.java | 4 +- .../java/org/jackhuang/hmcl/task/Task.java | 17 - 6 files changed, 19 insertions(+), 325 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/CancellableTaskExecutor.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 3ffd1a3fc2..c768dbfe59 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -206,7 +206,7 @@ else if ("Server".equals(configuration.getType())) "launch.state.dependencies", "launch.state.logging_in", "launch.state.waiting_launching")) - .cancellableExecutor(); + .executor(); launchingStepsPane.setExecutor(executor, false); executor.addTaskListener(new TaskListener() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java index 91b39d6bd7..fdb709b234 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/TaskExecutorDialogWizardDisplayer.java @@ -56,7 +56,7 @@ else if (title instanceof String) } runInFX(() -> { - TaskExecutor executor = task.cancellableExecutor(new TaskListener() { + TaskExecutor executor = task.executor(new TaskListener() { @Override public void onStop(boolean success, TaskExecutor executor) { runInFX(() -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java index a3b28474b4..ca7e35f531 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java @@ -107,6 +107,9 @@ private CompletableFuture executeTasks(Task parentTask, Collection .thenComposeAsync(unused -> { totTask.addAndGet(tasks.size()); + if (isCancelled()) + return CompletableFuture.runAsync(this::checkCancellation); + return CompletableFuture.allOf(tasks.stream() .map(task -> CompletableFuture.completedFuture(null) .thenComposeAsync(unused2 -> executeTask(parentTask, task)) @@ -125,8 +128,12 @@ private CompletableFuture executeTasks(Task parentTask, Collection } private CompletableFuture executeTask(Task parentTask, Task task) { + checkCancellation(); + return CompletableFuture.completedFuture(null) .thenComposeAsync(unused -> { + checkCancellation(); + task.setCancelled(this::isCancelled); task.setState(Task.TaskState.READY); if (parentTask != null && task.getStage() == null) @@ -187,6 +194,8 @@ private CompletableFuture executeTask(Task parentTask, Task task) { rethrow(dependenciesException); } + checkCancellation(); + if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); } @@ -253,6 +262,12 @@ private static Runnable wrap(ExceptionalRunnable runnable) { }; } + private void checkCancellation() { + if (isCancelled()) { + throw new CancellationException("Cancelled by user"); + } + } + private static Thread.UncaughtExceptionHandler uncaughtExceptionHandler = null; public static void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CancellableTaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CancellableTaskExecutor.java deleted file mode 100644 index c505a1ff9f..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CancellableTaskExecutor.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.task; - -import org.jackhuang.hmcl.util.Logging; -import org.jackhuang.hmcl.util.function.ExceptionalRunnable; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.UnaryOperator; -import java.util.logging.Level; - -public class CancellableTaskExecutor extends TaskExecutor { - - private final ConcurrentLinkedQueue> workerQueue = new ConcurrentLinkedQueue<>(); - private Executor scheduler = Schedulers.newThread(); - - public CancellableTaskExecutor(Task task) { - super(task); - } - - @Override - public TaskExecutor start() { - taskListeners.forEach(TaskListener::onStart); - workerQueue.add(Schedulers.schedule(scheduler, wrap(() -> { - boolean flag = executeTasks(null, Collections.singleton(firstTask)); - taskListeners.forEach(it -> it.onStop(flag, this)); - }))); - return this; - } - - @Override - public boolean test() { - taskListeners.forEach(TaskListener::onStart); - AtomicBoolean flag = new AtomicBoolean(true); - Future future = Schedulers.schedule(scheduler, wrap(() -> { - flag.set(executeTasks(null, Collections.singleton(firstTask))); - taskListeners.forEach(it -> it.onStop(flag.get(), this)); - })); - workerQueue.add(future); - try { - future.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (ExecutionException | CancellationException ignored) { - } - return flag.get(); - } - - @Override - public synchronized void cancel() { - cancelled.set(true); - - while (!workerQueue.isEmpty()) { - Future future = workerQueue.poll(); - if (future != null) - future.cancel(true); - } - } - - private boolean executeTasks(Task parentTask, Collection> tasks) throws InterruptedException { - if (tasks.isEmpty()) - return true; - - totTask.addAndGet(tasks.size()); - AtomicBoolean success = new AtomicBoolean(true); - CountDownLatch latch = new CountDownLatch(tasks.size()); - for (Task task : tasks) { - if (cancelled.get()) - return false; - Invoker invoker = new Invoker(parentTask, task, latch, success); - try { - Future future = Schedulers.schedule(scheduler, invoker); - workerQueue.add(future); - } catch (RejectedExecutionException e) { - throw new InterruptedException(); - } - } - - if (cancelled.get()) - return false; - - try { - latch.await(); - } catch (InterruptedException e) { - return false; - } - return success.get() && !cancelled.get(); - } - - private synchronized void updateStageProperties(String stage, Map taskProperties) { - stageProperties.putIfAbsent(stage, new HashMap<>()); - Map prop = stageProperties.get(stage); - for (Map.Entry entry : taskProperties.entrySet()) { - if (entry.getValue() instanceof UnaryOperator) { - prop.put(entry.getKey(), ((UnaryOperator) entry.getValue()).apply(prop.get(entry.getKey()))); - } else { - prop.put(entry.getKey(), entry.getValue()); - } - } - taskListeners.forEach(taskListener -> taskListener.onPropertiesUpdate(stageProperties)); - } - - private boolean executeTask(Task parentTask, Task task) { - task.setCancelled(this::isCancelled); - - if (cancelled.get()) { - task.setState(Task.TaskState.FAILED); - task.setException(new CancellationException()); - return false; - } - - task.setState(Task.TaskState.READY); - if (parentTask != null && task.getStage() == null) - task.setStage(parentTask.getStage()); - - if (task.getSignificance().shouldLog()) - Logging.LOG.log(Level.FINE, "Executing task: " + task.getName()); - - taskListeners.forEach(it -> it.onReady(task)); - - boolean flag = false; - - try { - if (task.doPreExecute()) { - try { - Schedulers.schedule(task.getExecutor(), wrap(task::preExecute)).get(); - } catch (ExecutionException e) { - rethrow(e); - } - } - - Collection> dependents = task.getDependents(); - boolean doDependentsSucceeded = executeTasks(task, dependents); - Exception dependentsException = dependents.stream().map(Task::getException) - .filter(Objects::nonNull) - .filter(x -> !(x instanceof CancellationException)) - .filter(x -> !(x instanceof InterruptedException)) - .findAny().orElse(null); - if (!doDependentsSucceeded && task.isRelyingOnDependents() || cancelled.get()) { - task.setException(dependentsException); - throw new ExecutionException(dependentsException); - } - - if (doDependentsSucceeded) - task.setDependentsSucceeded(); - - try { - Schedulers.schedule(task.getExecutor(), wrap(() -> { - task.setState(Task.TaskState.RUNNING); - taskListeners.forEach(it -> it.onRunning(task)); - task.execute(); - })).get(); - } catch (ExecutionException e) { - rethrow(e); - } finally { - task.setState(Task.TaskState.EXECUTED); - } - - if (task.properties != null) { - updateStageProperties(task.getStage(), task.properties); - } - - Collection> dependencies = task.getDependencies(); - boolean doDependenciesSucceeded = executeTasks(task, dependencies); - Exception dependenciesException = dependencies.stream().map(Task::getException) - .filter(Objects::nonNull) - .filter(x -> !(x instanceof CancellationException)) - .filter(x -> !(x instanceof InterruptedException)) - .findAny().orElse(null); - - if (doDependenciesSucceeded) - task.setDependenciesSucceeded(); - - if (task.doPostExecute()) { - try { - Schedulers.schedule(task.getExecutor(), wrap(task::postExecute)).get(); - } catch (ExecutionException e) { - rethrow(e); - } - } - - if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) { - Logging.LOG.severe("Subtasks failed for " + task.getName()); - task.setException(dependenciesException); - throw new ExecutionException(dependenciesException); - } - - flag = true; - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINER, "Task finished: " + task.getName()); - } - - if (task.properties != null) { - updateStageProperties(task.getStage(), task.properties); - } - - task.onDone().fireEvent(new TaskEvent(this, task, false)); - taskListeners.forEach(it -> it.onFinished(task)); - } catch (RejectedExecutionException e) { - Logging.LOG.log(Level.SEVERE, "Task rejected: " + task.getName(), e); - } catch (Exception throwable) { - Throwable resolved = resolveException(throwable); - if (resolved instanceof Exception) { - Exception e = (Exception) resolved; - if (e instanceof InterruptedException || e instanceof CancellationException) { - task.setException(e); - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); - } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } else { - task.setException(e); - exception = e; - if (task.getSignificance().shouldLog()) { - Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); - } - task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListeners.forEach(it -> it.onFailed(task, e)); - } - } else if (resolved instanceof Error) { - throw (Error) resolved; - } - } - task.setState(flag ? Task.TaskState.SUCCEEDED : Task.TaskState.FAILED); - return flag; - } - - private static Throwable resolveException(Throwable e) { - if (e instanceof ExecutionException || e instanceof CompletionException) - return resolveException(e.getCause()); - else - return e; - } - - private static void rethrow(Throwable e) { - if (e == null) - return; - if (e instanceof ExecutionException || e instanceof CompletionException) { // including UncheckedException and UncheckedThrowable - rethrow(e.getCause()); - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new CompletionException(e); - } - } - - private static Runnable wrap(ExceptionalRunnable runnable) { - return () -> { - try { - runnable.run(); - } catch (Exception e) { - rethrow(e); - } - }; - } - - private class Invoker implements Runnable { - - private final Task parentTask; - private final Task task; - private final CountDownLatch latch; - private final AtomicBoolean success; - - public Invoker(Task parentTask, Task task, CountDownLatch latch, AtomicBoolean success) { - this.parentTask = parentTask; - this.task = task; - this.latch = latch; - this.success = success; - } - - @Override - public void run() { - String oldName = Thread.currentThread().getName(); - try { - if (task.getName() != null) - Thread.currentThread().setName(task.getName()); - if (!executeTask(parentTask, task)) - success.set(false); - } finally { - Thread.currentThread().setName(oldName); - latch.countDown(); - } - } - - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java index 3f49b6c065..d825a99d3c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java @@ -143,13 +143,13 @@ public void execute() throws Exception { lastDownloaded = downloaded; } + if (isCancelled()) break download; + updateDownloadSpeed(downloaded - lastDownloaded); if (contentLength >= 0 && downloaded != contentLength) throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength); - if (isCancelled()) break download; - context.withResult(true); } 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 54d32264db..44782c7b84 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -376,23 +376,6 @@ public final TaskExecutor executor(TaskListener taskListener) { return executor; } - public final TaskExecutor cancellableExecutor() { - return new CancellableTaskExecutor(this); - } - - public final TaskExecutor cancellableExecutor(boolean start) { - TaskExecutor executor = new CancellableTaskExecutor(this); - if (start) - executor.start(); - return executor; - } - - public final TaskExecutor cancellableExecutor(TaskListener taskListener) { - TaskExecutor executor = new CancellableTaskExecutor(this); - executor.addTaskListener(taskListener); - return executor; - } - public final void start() { executor().start(); } From 2de6a45ca1497caedfa5bab3c06a8b48ebc8b69d Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 19:16:09 +0800 Subject: [PATCH 0414/2639] fix: #759 --- .../java/org/jackhuang/hmcl/ui/decorator/Decorator.java | 9 ++++++++- .../jackhuang/hmcl/ui/decorator/DecoratorController.java | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java index eecb72e608..cc6b899011 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java @@ -226,9 +226,16 @@ public void close() { } public void capableDraggingWindow(Node node) { - node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove.set(true)); + node.addEventHandler(MouseEvent.MOUSE_MOVED, e -> allowMove.set(true)); node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { if (!isDragging()) allowMove.set(false); }); } + + public void forbidDraggingWindow(Node node) { + node.addEventHandler(MouseEvent.MOUSE_MOVED, e -> { + allowMove.set(false); + e.consume(); + }); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index a6db838393..ca2b973a2a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -307,6 +307,7 @@ public void showDialog(Node node) { dialog.setContent(dialogPane); decorator.capableDraggingWindow(dialog); + decorator.forbidDraggingWindow(dialogPane); dialog.setDialogContainer(decorator.getDrawerWrapper()); dialog.setOverlayClose(false); dialog.show(); From 58819b636151e1caa3b3a560eaf45a11e93b91c2 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 19:20:52 +0800 Subject: [PATCH 0415/2639] fix: test --- .../main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java index ca7e35f531..5d960ffcb5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/AsyncTaskExecutor.java @@ -210,7 +210,7 @@ private CompletableFuture executeTask(Task parentTask, Task task) { if (resolved instanceof Exception) { Exception e = (Exception) resolved; if (e instanceof InterruptedException || e instanceof CancellationException) { - task.setException(e); + task.setException(null); if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName()); } From 5bbb565bd44334fc3e5c69ba8b6285633d878fac Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 19:24:49 +0800 Subject: [PATCH 0416/2639] add: #762 --- .../hmcl/setting/DownloadProviders.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) 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 5a2c12351d..3b16ebf897 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java @@ -37,13 +37,21 @@ private DownloadProviders() {} private static final AdaptedDownloadProvider DOWNLOAD_PROVIDER = new AdaptedDownloadProvider(); - public static final Map providersById = mapOf( - pair("mojang", new MojangDownloadProvider()), - pair("bmclapi", new BMCLAPIDownloadProvider("https://bmclapi2.bangbang93.com")), - pair("mcbbs", new BMCLAPIDownloadProvider("https://download.mcbbs.net"))); + public static final Map providersById; public static final String DEFAULT_PROVIDER_ID = "mcbbs"; + static { + String bmclapiRoot = "https://bmclapi2.bangbang93.com"; + String bmclapiRootOverride = System.getProperty("hmcl.bmclapi.override"); + if (bmclapiRootOverride != null) bmclapiRoot = bmclapiRootOverride; + + providersById = mapOf( + pair("mojang", new MojangDownloadProvider()), + pair("bmclapi", new BMCLAPIDownloadProvider(bmclapiRoot)), + pair("mcbbs", new BMCLAPIDownloadProvider("https://download.mcbbs.net"))); + } + static void init() { FXUtils.onChangeAndOperate(config().downloadTypeProperty(), downloadType -> { DownloadProvider primary = Optional.ofNullable(providersById.get(config().getDownloadType())) From 66459a124c2bb739db4733844b6c71698b82b6e2 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 19:28:15 +0800 Subject: [PATCH 0417/2639] add: readme for bmclapi overrides --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f767276ed1..3e9f61d2ea 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Make sure you have Java installed with Pack200 and JavaFX 8 at least. Liberica f |Parameter|Description| |---------|-----------| |`-Dhmcl.self_integrity_check.disable=true`|Bypass the self integrity check when checking for update.| +|`-Dhmcl.bmclapi.override=`|Override api root of BMCLAPI download provider, defaults to `https://bmclapi2.bangbang93.com`. e.g. `https://download.mcbbs.net`.| |`-Dhmcl.font.override=`|Override font family.| |`-Dhmcl.version.override=`|Override the version number.| |`-Dhmcl.update_source.override=`|Override the update source.| From 1d66ebef5847e5abcb7447fff4e7552020ce13de Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 9 Aug 2020 19:44:48 +0800 Subject: [PATCH 0418/2639] add: #757. --- .../jackhuang/hmcl/game/HMCLGameLauncher.java | 30 +++++++++++++++++++ .../org/jackhuang/hmcl/util/i18n/I18n.java | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) 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 fb7cb66a61..bab78d7e29 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java @@ -21,8 +21,16 @@ import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.launch.DefaultLauncher; import org.jackhuang.hmcl.launch.ProcessListener; +import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.i18n.I18n; +import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.platform.ManagedProcess; +import java.io.File; +import java.io.IOException; +import java.util.Locale; import java.util.Map; +import java.util.logging.Level; /** * @author huangyuhui @@ -48,4 +56,26 @@ protected Map getConfigurations() { res.put("${launcher_version}", Metadata.VERSION); return res; } + + private void generateOptionsTxt() { + try { + // TODO: Dirty implementation here + if (I18n.getCurrentLocale().getLocale() == Locale.CHINA) + FileUtils.writeText(new File(repository.getRunDirectory(version.getId()), "options.txt"), "lang:zh_cn\nforceUnicodeFont:true\n"); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to generate options.txt", e); + } + } + + @Override + public ManagedProcess launch() throws IOException, InterruptedException { + generateOptionsTxt(); + return super.launch(); + } + + @Override + public void makeLaunchScript(File scriptFile) throws IOException { + generateOptionsTxt(); + super.makeLaunchScript(scriptFile); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/I18n.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/I18n.java index 0d851312f2..056fcda107 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/I18n.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/I18n.java @@ -30,7 +30,7 @@ public final class I18n { private I18n() {} - private static SupportedLocale getCurrentLocale() { + public static SupportedLocale getCurrentLocale() { try { return ConfigHolder.config().getLocalization(); } catch (IllegalStateException e) { From 94b2cafa7a70df9d399557806985f30a56301f87 Mon Sep 17 00:00:00 2001 From: BBleae Date: Mon, 10 Aug 2020 17:59:35 +0800 Subject: [PATCH 0419/2639] fix: override options.txt --- .../main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 bab78d7e29..24caabc4f8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java @@ -58,10 +58,13 @@ protected Map getConfigurations() { } private void generateOptionsTxt() { + File optionsFile = new File(repository.getRunDirectory(version.getId()), "options.txt"); + if (optionsFile.exists()) + return; try { // TODO: Dirty implementation here if (I18n.getCurrentLocale().getLocale() == Locale.CHINA) - FileUtils.writeText(new File(repository.getRunDirectory(version.getId()), "options.txt"), "lang:zh_cn\nforceUnicodeFont:true\n"); + FileUtils.writeText(optionsFile, "lang:zh_cn\nforceUnicodeFont:true\n"); } catch (IOException e) { Logging.LOG.log(Level.WARNING, "Unable to generate options.txt", e); } From c3f19d2c4a03accb1185b0656456149a15aea16d Mon Sep 17 00:00:00 2001 From: BBleae Date: Mon, 10 Aug 2020 21:38:44 +0800 Subject: [PATCH 0420/2639] perf: cache Java version from executable. --- .../hmcl/util/platform/JavaVersion.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java index c18310be6c..c2cafc864b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java @@ -30,6 +30,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import java.util.regex.Matcher; @@ -108,12 +110,17 @@ else if (version.contains("1.7")) return UNKNOWN; } + private static final Map fromExecutableCache = new ConcurrentHashMap<>(); + public static JavaVersion fromExecutable(Path executable) throws IOException { + executable = executable.toRealPath(); + JavaVersion cachedJavaVersion = fromExecutableCache.get(executable); + if (cachedJavaVersion != null) + return cachedJavaVersion; + Platform platform = Platform.BIT_32; String version = null; - executable = executable.toRealPath(); - Process process = new ProcessBuilder(executable.toString(), "-version").start(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { for (String line; (line = reader.readLine()) != null;) { @@ -130,8 +137,9 @@ public static JavaVersion fromExecutable(Path executable) throws IOException { if (parseVersion(version) == UNKNOWN) throw new IOException("Unrecognized Java version " + version); - - return new JavaVersion(executable, version, platform); + JavaVersion javaVersion = new JavaVersion(executable, version, platform); + fromExecutableCache.put(executable, javaVersion); + return javaVersion; } private static Path getExecutable(Path javaHome) { From 7f674f237be8fee88788739ae5fcda935d75672e Mon Sep 17 00:00:00 2001 From: xtex Date: Tue, 11 Aug 2020 11:25:23 +0800 Subject: [PATCH 0421/2639] fix: #769 --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index f8443b1ce3..0d4c564d66 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ version '3.0' subprojects { apply plugin: 'java' apply plugin: 'idea' + apply plugin: 'maven-publish' apply plugin: 'com.github.hierynomus.license' repositories { @@ -46,6 +47,17 @@ subprojects { java='SLASHSTAR_STYLE' } } + + publishing { + publications { + maven(MavenPublication) { + from components.java + } + } + repositories { + mavenLocal() + } + } } defaultTasks 'clean', 'build' From 2f109482393e071903674d05e9bb4834237c3d90 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Wed, 12 Aug 2020 21:49:46 +0800 Subject: [PATCH 0422/2639] implement yushijinhun/authlib-injector#78 --- .../AuthlibInjectorServer.java | 72 +++++-------------- 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java index 6b01d7663c..bd72cc9bd1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java @@ -27,9 +27,7 @@ import java.io.IOException; import java.lang.reflect.Type; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; -import java.net.URLConnection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @@ -56,30 +54,25 @@ @JsonAdapter(AuthlibInjectorServer.Deserializer.class) public class AuthlibInjectorServer implements Observable { - private static final int MAX_REDIRECTS = 5; private static final Gson GSON = new GsonBuilder().create(); public static AuthlibInjectorServer locateServer(String url) throws IOException { try { - url = parseInputUrl(url); - HttpURLConnection conn; - int redirectCount = 0; - for (; ; ) { - conn = (HttpURLConnection) new URL(url).openConnection(); - Optional ali = getApiLocationIndication(conn); - if (ali.isPresent()) { + url = addHttpsIfMissing(url); + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + + String ali = conn.getHeaderField("x-authlib-injector-api-location"); + if (ali != null) { + URL absoluteAli = new URL(conn.getURL(), ali); + if (!urlEqualsIgnoreSlash(url, absoluteAli.toString())) { conn.disconnect(); - url = ali.get(); - if (redirectCount >= MAX_REDIRECTS) { - throw new IOException("Exceeded maximum number of redirects (" + MAX_REDIRECTS + ")"); - } - redirectCount++; - LOG.info("Redirect API root to: " + url); - } else { - break; + url = absoluteAli.toString(); + conn = (HttpURLConnection) absoluteAli.openConnection(); } } + if (!url.endsWith("/")) + url += "/"; try { AuthlibInjectorServer server = new AuthlibInjectorServer(url); @@ -93,49 +86,20 @@ public static AuthlibInjectorServer locateServer(String url) throws IOException } } - private static Optional getApiLocationIndication(URLConnection conn) { - return Optional.ofNullable(conn.getHeaderFields().get("X-Authlib-Injector-API-Location")) - .flatMap(list -> list.isEmpty() ? Optional.empty() : Optional.of(list.get(0))) - .flatMap(indication -> { - String currentUrl = appendSuffixSlash(conn.getURL().toString()); - String newUrl; - try { - newUrl = appendSuffixSlash(new URL(conn.getURL(), indication).toString()); - } catch (MalformedURLException e) { - LOG.warning("Failed to resolve absolute ALI, the header is [" + indication + "]. Ignore it."); - return Optional.empty(); - } - - if (newUrl.equals(currentUrl)) { - return Optional.empty(); - } else { - return Optional.of(newUrl); - } - }); - } - - private static String parseInputUrl(String url) { + private static String addHttpsIfMissing(String url) { String lowercased = url.toLowerCase(); if (!lowercased.startsWith("http://") && !lowercased.startsWith("https://")) { url = "https://" + url; } - - url = appendSuffixSlash(url); return url; } - private static String appendSuffixSlash(String url) { - if (!url.endsWith("/")) { - return url + "/"; - } else { - return url; - } - } - - public static AuthlibInjectorServer fetchServerInfo(String url) throws IOException { - AuthlibInjectorServer server = new AuthlibInjectorServer(url); - server.refreshMetadata(); - return server; + private static boolean urlEqualsIgnoreSlash(String a, String b) { + if (!a.endsWith("/")) + a += "/"; + if (!b.endsWith("/")) + b += "/"; + return a.equals(b); } private String url; From 48e2fcc601f9d58140258746008e601d7418a7e6 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 15 Aug 2020 17:04:29 +0800 Subject: [PATCH 0423/2639] Set Locale.default to selected language e6d11fe9a35cc94ecd8c67b1008cef48f1fb79a4 is broken because Locale.default is not set by HMCL at all. This commit fixes the bug. Note that now if we want to obtain the system language, we must use Locales.DEFAULT rather than Locale.getDefault(). --- .../main/java/org/jackhuang/hmcl/setting/Settings.java | 9 +++++++++ 1 file changed, 9 insertions(+) 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 b46830dada..6623d5dab1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -25,6 +25,8 @@ import static org.jackhuang.hmcl.setting.ConfigHolder.config; +import java.util.Locale; + public class Settings { private static Settings instance; @@ -44,6 +46,9 @@ static void init() { } private Settings() { + config().localizationProperty().addListener(unused -> updateSystemLocale()); + updateSystemLocale(); + DownloadProviders.init(); ProxyManager.init(); Accounts.init(); @@ -74,4 +79,8 @@ public String getCommonDirectory() { return null; } } + + private static void updateSystemLocale() { + Locale.setDefault(config().getLocalization().getLocale()); + } } From 88c595dab244d56ad8e840bc8e833cfe1ba90706 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 15 Aug 2020 17:13:43 +0800 Subject: [PATCH 0424/2639] Remove 'ForbiddenOperationException' from auth error message --- .../main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 1b1ab32706..44389c7d84 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -317,6 +317,8 @@ else if (remoteMessage.contains("Invalid token")) return i18n("account.failed.invalid_token"); else if (remoteMessage.contains("Invalid username or password")) return i18n("account.failed.invalid_password"); + else + return remoteMessage; } return exception.getMessage(); } else if (exception instanceof AuthlibInjectorDownloadException) { From cafcb74e223d93ad19501b847910407ecb3ad669 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sun, 16 Aug 2020 14:51:57 +0800 Subject: [PATCH 0425/2639] fix: #774 --- .../main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 904087ca0c..6e3a87948b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -202,7 +202,7 @@ private CommandBuilder generateCommandLine(File nativeFolder) throws IOException if (options.isFullscreen()) res.add("--fullscreen"); - if (options.getProxy() != null) { + if (options.getProxy() != null && options.getProxy().type() == Proxy.Type.SOCKS) { InetSocketAddress address = (InetSocketAddress) options.getProxy().address(); if (address != null) { res.add("--proxyHost"); From 674dfca34dc08160f9dd16962689bf20b8248794 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 27 Aug 2020 11:19:52 +0800 Subject: [PATCH 0426/2639] fix: #784 --- .../hmcl/download/game/LibraryDownloadException.java | 3 ++- .../org/jackhuang/hmcl/download/game/LibraryDownloadTask.java | 3 +++ .../main/java/org/jackhuang/hmcl/task/DownloadException.java | 4 +++- HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java | 2 ++ 4 files changed, 10 insertions(+), 2 deletions(-) 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 index 086402830f..10af82acb5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadException.java @@ -18,11 +18,12 @@ package org.jackhuang.hmcl.download.game; import org.jackhuang.hmcl.game.Library; +import org.jetbrains.annotations.NotNull; public class LibraryDownloadException extends Exception { private final Library library; - public LibraryDownloadException(Library library, Throwable cause) { + public LibraryDownloadException(Library library, @NotNull Throwable cause) { super("Unable to download library " + library, cause); this.library = 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 106fbc3672..3d308940c7 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 @@ -37,6 +37,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.concurrent.CancellationException; import java.util.jar.*; import java.util.logging.Level; @@ -95,6 +96,8 @@ public void execute() throws Exception { Exception t = task.getException(); if (t instanceof DownloadException) throw new LibraryDownloadException(library, t.getCause()); + else if (t == null) + throw new CancellationException(); else throw new LibraryDownloadException(library, t); } else { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java index e6411410b7..55d7b1cc77 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/DownloadException.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.task; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.net.URL; @@ -26,7 +28,7 @@ public class DownloadException extends IOException { private final URL url; - public DownloadException(URL url, Throwable cause) { + public DownloadException(URL url, @NotNull Throwable cause) { super("Unable to download " + url + ", " + cause.getMessage(), requireNonNull(cause)); this.url = url; 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 44782c7b84..f2441025a5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -31,6 +31,7 @@ import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalRunnable; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; +import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.Callable; @@ -131,6 +132,7 @@ final void setState(TaskState state) { * * @return the exception thrown during execution, possibly from dependents or dependencies. */ + @Nullable public final Exception getException() { return exception; } From 5a81972f68e64cbaaea8599dae8f0eb461c6fb43 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Thu, 27 Aug 2020 02:44:12 +0800 Subject: [PATCH 0427/2639] impl https://github.com/yushijinhun/authlib-injector/issues/85 --- .../hmcl/ui/account/AddAccountPane.java | 22 +++++++++++++++---- .../AuthlibInjectorServer.java | 8 +++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 44389c7d84..0175791d99 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -114,7 +114,7 @@ public AddAccountPane() { cboServers.visibleProperty().bind(loginType.isEqualTo(Accounts.FACTORY_AUTHLIB_INJECTOR)); lblInjectorServer.visibleProperty().bind(cboServers.visibleProperty()); - txtUsername.getValidators().add(new Validator(i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@"))); + txtUsername.getValidators().add(new Validator(i18n("input.email"), this::validateUsername)); btnAccept.disableProperty().bind(Bindings.createBooleanBinding( () -> !( // consider the opposite situation: input is valid @@ -123,9 +123,9 @@ public AddAccountPane() { (!txtPassword.isVisible() || txtPassword.validate()) && (!cboServers.isVisible() || cboServers.getSelectionModel().getSelectedItem() != null) ), - txtUsername.textProperty(), - txtPassword.textProperty(), txtPassword.visibleProperty(), - cboServers.getSelectionModel().selectedItemProperty(), cboServers.visibleProperty())); + txtUsername.textProperty(), txtPassword.textProperty(), + loginType, cboServers.getSelectionModel().selectedItemProperty(), + txtPassword.visibleProperty(), cboServers.visibleProperty())); // authlib-injector links links.bind(BindingMapping.of(cboServers.getSelectionModel().selectedItemProperty()) @@ -135,6 +135,20 @@ public AddAccountPane() { linksContainer.visibleProperty().bind(cboServers.visibleProperty()); } + private boolean validateUsername(String username) { + AccountFactory loginType = cboType.getSelectionModel().getSelectedItem(); + if (loginType == Accounts.FACTORY_OFFLINE) { + return true; + } else if (loginType == Accounts.FACTORY_AUTHLIB_INJECTOR) { + AuthlibInjectorServer server = cboServers.getSelectionModel().getSelectedItem(); + if (server != null && server.isNonEmailLogin()) { + return true; + } + } + + return username.contains("@"); + } + private static final String[] ALLOWED_LINKS = { "register" }; public static List createHyperlinks(AuthlibInjectorServer server) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java index bd72cc9bd1..282c225998 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java @@ -110,6 +110,7 @@ private static boolean urlEqualsIgnoreSlash(String a, String b) { @Nullable private transient String name; private transient Map links = emptyMap(); + private transient boolean nonEmailLogin; private transient boolean metadataRefreshed; private final transient ObservableHelper helper = new ObservableHelper(this); @@ -145,6 +146,10 @@ public Map getLinks() { return links; } + public boolean isNonEmailLogin() { + return nonEmailLogin; + } + public String fetchMetadataResponse() throws IOException { if (metadataResponse == null || !metadataRefreshed) { refreshMetadata(); @@ -194,6 +199,9 @@ private void setMetadataResponse(String metadataResponse, long metadataTimestamp return converted; }) .orElse(emptyMap()); + this.nonEmailLogin = metaObject.flatMap(meta -> tryCast(meta.get("feature.non_email_login"), JsonPrimitive.class)) + .map(it -> it.getAsBoolean()) + .orElse(false); } } From f4f1850271aebd8bab8a8b3bde46ff18b5360f70 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 4 Sep 2020 00:38:38 +0800 Subject: [PATCH 0428/2639] fix: try to fix blocking game running when launcher visibility was set to close after game started. --- .../main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 6e3a87948b..211801a229 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -323,6 +323,9 @@ public ManagedProcess launch() throws IOException, InterruptedException { Process process; try { ProcessBuilder builder = new ProcessBuilder(rawCommandLine).directory(runDirectory); + if (listener == null) { + builder.inheritIO(); + } String appdata = options.getGameDir().getAbsoluteFile().getParent(); if (appdata != null) builder.environment().put("APPDATA", appdata); process = builder.start(); From 4715a95a54c0e2b40fda4195d0181eb33291641b Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Sat, 22 Aug 2020 21:33:10 +0800 Subject: [PATCH 0429/2639] feat: initial multithreaded downloading --- .../jackhuang/hmcl/game/LauncherHelper.java | 4 +- .../org/jackhuang/hmcl/task/FetchTask.java | 81 +++++++++++++++++++ .../org/jackhuang/hmcl/task/Schedulers.java | 48 +++++------ 3 files changed, 104 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 c768dbfe59..1d54cdc152 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -109,7 +109,7 @@ public void launch() { try { checkGameState(profile, setting, version, () -> { Controllers.dialog(launchingStepsPane); - Schedulers.newThread().execute(this::launch0); + Schedulers.defaultScheduler().execute(this::launch0); }); } catch (InterruptedException | RejectedExecutionException ignore) { } @@ -199,7 +199,7 @@ else if ("Server".equals(configuration.getType())) Controllers.dialog(i18n("version.launch_script.success", scriptFile.getAbsolutePath())); }); } - }).thenRunAsync(Schedulers.defaultScheduler(), () -> { + }).thenRunAsync(() -> { launchingLatch.await(); }).withStage("launch.state.waiting_launching")) .withStagesHint(Lang.immutableListOf( diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java index d825a99d3c..ecc1041f69 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java @@ -34,6 +34,7 @@ import java.net.URLConnection; import java.nio.file.Path; import java.util.*; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -225,4 +226,84 @@ protected enum EnumCheckETag { NOT_CHECK_E_TAG, CACHED } + + protected class DownloadState { + private final int startPosition; + private final int endPosition; + private final int currentPosition; + private final boolean finished; + + public DownloadState(int startPosition, int endPosition, int currentPosition) { + if (currentPosition < startPosition || currentPosition > endPosition) { + throw new IllegalArgumentException("Illegal download state: start " + startPosition + ", end " + endPosition + ", cur " + currentPosition); + } + this.startPosition = startPosition; + this.endPosition = endPosition; + this.currentPosition = currentPosition; + finished = currentPosition == endPosition; + } + + public int getStartPosition() { + return startPosition; + } + + public int getEndPosition() { + return endPosition; + } + + public int getCurrentPosition() { + return currentPosition; + } + + public boolean isFinished() { + return finished; + } + } + + protected class DownloadMission { + + + + } + + private static int downloadExecutorConcurrency = Math.min(Runtime.getRuntime().availableProcessors() * 4, 64); + private static volatile ExecutorService DOWNLOAD_EXECUTOR; + + /** + * Get singleton instance of the thread pool for file downloading. + * + * @return Thread pool for FetchTask + */ + protected static ExecutorService download() { + if (DOWNLOAD_EXECUTOR == null) { + synchronized (Schedulers.class) { + if (DOWNLOAD_EXECUTOR == null) { + DOWNLOAD_EXECUTOR = new ThreadPoolExecutor(0, downloadExecutorConcurrency, 10, TimeUnit.SECONDS, new SynchronousQueue<>(), + runnable -> { + Thread thread = Executors.defaultThreadFactory().newThread(runnable); + thread.setDaemon(true); + return thread; + }); + } + } + } + + return DOWNLOAD_EXECUTOR; + } + + public static void setDownloadExecutorConcurrency(int concurrency) { + synchronized (Schedulers.class) { + downloadExecutorConcurrency = concurrency; + if (DOWNLOAD_EXECUTOR != null) { + DOWNLOAD_EXECUTOR.shutdownNow(); + DOWNLOAD_EXECUTOR = null; + } + } + } + + public static int getDownloadExecutorConcurrency() { + synchronized (Schedulers.class) { + return downloadExecutorConcurrency; + } + } } 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 d8397207b4..b53cab1862 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -32,27 +32,29 @@ public final class Schedulers { private Schedulers() { } - private static volatile ThreadPoolExecutor CACHED_EXECUTOR; - - public static synchronized ThreadPoolExecutor newThread() { - if (CACHED_EXECUTOR == null) - CACHED_EXECUTOR = new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60, TimeUnit.SECONDS, new SynchronousQueue<>(), Executors.defaultThreadFactory()); - - return CACHED_EXECUTOR; - } - private static volatile ExecutorService IO_EXECUTOR; - public static synchronized ExecutorService io() { + /** + * Get singleton instance of the thread pool for I/O operations, + * usually for reading files from disk, or Internet connections. + * + * This thread pool has no more than 4 threads, and number of threads will get + * reduced if concurrency is less than thread number. + * + * @return Thread pool for I/O operations. + */ + public static ExecutorService io() { if (IO_EXECUTOR == null) { - int threads = Math.min(Runtime.getRuntime().availableProcessors() * 4, 64); - IO_EXECUTOR = Executors.newFixedThreadPool(threads, - runnable -> { - Thread thread = Executors.defaultThreadFactory().newThread(runnable); - thread.setDaemon(true); - return thread; - }); + synchronized (Schedulers.class) { + if (IO_EXECUTOR == null) { + IO_EXECUTOR = new ThreadPoolExecutor(0, 4, 10, TimeUnit.SECONDS, new SynchronousQueue<>(), + runnable -> { + Thread thread = Executors.defaultThreadFactory().newThread(runnable); + thread.setDaemon(true); + return thread; + }); + } + } } return IO_EXECUTOR; @@ -67,7 +69,7 @@ public static Executor swing() { } public static Executor defaultScheduler() { - return newThread(); + return ForkJoinPool.commonPool(); } public static synchronized void shutdown() { @@ -77,16 +79,8 @@ public static synchronized void shutdown() { // So when we want to close the app, no threads need to be waited for finish. // Sometimes it resolves the problem that the app does not exit. - if (CACHED_EXECUTOR != null) - CACHED_EXECUTOR.shutdownNow(); - if (IO_EXECUTOR != null) IO_EXECUTOR.shutdownNow(); } - public static Future schedule(Executor executor, Runnable command) { - FutureTask future = new FutureTask(command, null); - executor.execute(future); - return future; - } } From c1911860239821b621884342b68161ec6bb9eaf3 Mon Sep 17 00:00:00 2001 From: yuhuihuang Date: Thu, 10 Dec 2020 21:47:53 +0800 Subject: [PATCH 0430/2639] feat: Microsoft Account authentication --- .../org/jackhuang/hmcl/setting/Accounts.java | 14 +- .../org/jackhuang/hmcl/ui/Controllers.java | 2 + .../java/org/jackhuang/hmcl/ui/WebStage.java | 15 +- .../hmcl/ui/account/AccountListItem.java | 4 +- .../hmcl/ui/account/AddAccountPane.java | 9 +- .../account/MicrosoftAccountLoginStage.java | 49 +++ .../resources/assets/fxml/account-add.fxml | 2 +- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_es.properties | 1 + .../resources/assets/lang/I18N_ru.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../jackhuang/hmcl/auth/AccountFactory.java | 45 +++ .../AuthlibInjectorAccountFactory.java | 5 + .../hmcl/auth/microsoft/MicrosoftAccount.java | 117 ++++++++ .../microsoft/MicrosoftAccountFactory.java | 36 +++ .../hmcl/auth/microsoft/MicrosoftService.java | 280 ++++++++++++++++++ .../hmcl/auth/microsoft/MicrosoftSession.java | 100 +++++++ .../auth/offline/OfflineAccountFactory.java | 5 + .../auth/yggdrasil/CompleteGameProfile.java | 5 +- .../hmcl/auth/yggdrasil/GameProfile.java | 13 +- .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 1 + .../yggdrasil/YggdrasilAccountFactory.java | 7 +- .../jackhuang/hmcl/util/gson/Validation.java | 5 + .../jackhuang/hmcl/util/io/HttpRequest.java | 133 +++++++++ .../jackhuang/hmcl/util/io/NetworkUtils.java | 4 +- 26 files changed, 835 insertions(+), 21 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/account/MicrosoftAccountLoginStage.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccountFactory.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftSession.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java 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 34a6801306..43b79e8031 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -34,15 +34,20 @@ import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloader; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.authlibinjector.SimpleAuthlibInjectorArtifactProvider; +import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount; +import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccountFactory; +import org.jackhuang.hmcl.auth.microsoft.MicrosoftService; import org.jackhuang.hmcl.auth.offline.OfflineAccount; import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory; import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.ui.account.MicrosoftAccountLoginStage; import java.io.IOException; import java.nio.file.Paths; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.logging.Level; @@ -51,6 +56,7 @@ import static javafx.collections.FXCollections.observableArrayList; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; +import static org.jackhuang.hmcl.util.Lang.immutableListOf; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Pair.pair; @@ -78,6 +84,8 @@ private static void triggerAuthlibInjectorUpdateCheck() { public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE; public static final YggdrasilAccountFactory FACTORY_MOJANG = YggdrasilAccountFactory.MOJANG; public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER, Accounts::getOrCreateAuthlibInjectorServer); + public static final MicrosoftAccountFactory FACTORY_MICROSOFT = new MicrosoftAccountFactory(new MicrosoftService(MicrosoftAccountLoginStage.INSTANCE)); + public static final List> FACTORIES = immutableListOf(FACTORY_OFFLINE, FACTORY_MOJANG, FACTORY_AUTHLIB_INJECTOR, FACTORY_MICROSOFT); // ==== login type / account factory mapping ==== private static final Map> type2factory = new HashMap<>(); @@ -86,6 +94,7 @@ private static void triggerAuthlibInjectorUpdateCheck() { type2factory.put("offline", FACTORY_OFFLINE); type2factory.put("yggdrasil", FACTORY_MOJANG); type2factory.put("authlibInjector", FACTORY_AUTHLIB_INJECTOR); + type2factory.put("microsoft", FACTORY_MICROSOFT); type2factory.forEach((type, factory) -> factory2type.put(factory, type)); } @@ -108,6 +117,8 @@ else if (account instanceof AuthlibInjectorAccount) return FACTORY_AUTHLIB_INJECTOR; else if (account instanceof YggdrasilAccount) return FACTORY_MOJANG; + else if (account instanceof MicrosoftAccount) + return FACTORY_MICROSOFT; else throw new IllegalArgumentException("Failed to determine account type: " + account); } @@ -309,7 +320,8 @@ private static void removeDanglingAuthlibInjectorAccounts() { private static Map, String> unlocalizedLoginTypeNames = mapOf( pair(Accounts.FACTORY_OFFLINE, "account.methods.offline"), pair(Accounts.FACTORY_MOJANG, "account.methods.yggdrasil"), - pair(Accounts.FACTORY_AUTHLIB_INJECTOR, "account.methods.authlib_injector")); + pair(Accounts.FACTORY_AUTHLIB_INJECTOR, "account.methods.authlib_injector"), + pair(Accounts.FACTORY_MICROSOFT, "account.methods.microsoft")); public static String getLocalizedLoginTypeName(AccountFactory factory) { return i18n(Optional.ofNullable(unlocalizedLoginTypeNames.get(factory)) 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 8407b81286..5642941688 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -31,6 +31,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage; +import org.jackhuang.hmcl.ui.account.MicrosoftAccountLoginStage; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.construct.InputDialogPane; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; @@ -107,6 +108,7 @@ public static void initialize(Stage stage) { Logging.LOG.info("Start initializing application"); Controllers.stage = stage; + MicrosoftAccountLoginStage.INSTANCE.initOwner(stage); stage.setHeight(config().getHeight()); stageHeight.bind(stage.heightProperty()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java index ba48788690..957a692df4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java @@ -17,7 +17,11 @@ */ package org.jackhuang.hmcl.ui; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.concurrent.Worker; import javafx.scene.Scene; +import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; @@ -25,12 +29,19 @@ import static org.jackhuang.hmcl.ui.FXUtils.newImage; public class WebStage extends Stage { - private final WebView webView = new WebView(); + protected final WebView webView = new WebView(); + protected final WebEngine webEngine = webView.getEngine(); public WebStage() { - setScene(new Scene(webView, 800, 480)); + this(800, 480); + } + + public WebStage(int width, int height) { + setScene(new Scene(webView, width, height)); getScene().getStylesheets().addAll(config().getTheme().getStylesheets()); getIcons().add(newImage("/assets/img/icon.png")); + webView.setContextMenuEnabled(false); + titleProperty().bind(webEngine.titleProperty()); } public WebView getWebView() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java index 8917c27a6d..e0a03614bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java @@ -73,7 +73,9 @@ public AccountListItem(Account account) { if (account instanceof OfflineAccount) { title.bind(characterName); } else { - title.bind(Bindings.concat(account.getUsername(), " - ", characterName)); + title.bind( + account.getUsername().isEmpty() ? characterName : + Bindings.concat(account.getUsername(), " - ", characterName)); } image.bind(TexturesLoader.fxAvatarBinding(account, 32)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 0175791d99..44242c45b0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -68,6 +68,7 @@ public class AddAccountPane extends StackPane { @FXML private JFXPasswordField txtPassword; @FXML private Label lblCreationWarning; @FXML private Label lblPassword; + @FXML private Label lblUsername; @FXML private JFXComboBox> cboType; @FXML private JFXComboBox cboServers; @FXML private Label lblInjectorServer; @@ -88,7 +89,7 @@ public AddAccountPane() { cboServers.getItems().addListener(onInvalidating(this::selectDefaultServer)); selectDefaultServer(); - cboType.getItems().setAll(Accounts.FACTORY_OFFLINE, Accounts.FACTORY_MOJANG, Accounts.FACTORY_AUTHLIB_INJECTOR); + cboType.getItems().setAll(Accounts.FACTORIES); cboType.setConverter(stringConverter(Accounts::getLocalizedLoginTypeName)); // try selecting the preferred login type cboType.getSelectionModel().select( @@ -108,7 +109,9 @@ public AddAccountPane() { // remember the last used login type loginType.addListener((observable, oldValue, newValue) -> config().setPreferredLoginType(Accounts.getLoginType(newValue))); - txtPassword.visibleProperty().bind(loginType.isNotEqualTo(Accounts.FACTORY_OFFLINE)); + txtUsername.visibleProperty().bind(Bindings.createBooleanBinding(() -> loginType.get().getLoginType().requiresUsername, loginType)); + lblUsername.visibleProperty().bind(txtUsername.visibleProperty()); + txtPassword.visibleProperty().bind(Bindings.createBooleanBinding(() -> loginType.get().getLoginType().requiresPassword, loginType)); lblPassword.visibleProperty().bind(txtPassword.visibleProperty()); cboServers.visibleProperty().bind(loginType.isEqualTo(Accounts.FACTORY_AUTHLIB_INJECTOR)); @@ -118,7 +121,7 @@ public AddAccountPane() { btnAccept.disableProperty().bind(Bindings.createBooleanBinding( () -> !( // consider the opposite situation: input is valid - txtUsername.validate() && + (!txtUsername.isVisible() || txtUsername.validate()) && // invisible means the field is not needed, neither should it be validated (!txtPassword.isVisible() || txtPassword.validate()) && (!cboServers.isVisible() || cboServers.getSelectionModel().getSelectedItem() != null) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/MicrosoftAccountLoginStage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/MicrosoftAccountLoginStage.java new file mode 100644 index 0000000000..ad3df1b858 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/MicrosoftAccountLoginStage.java @@ -0,0 +1,49 @@ +package org.jackhuang.hmcl.ui.account; + +import javafx.application.Platform; +import javafx.stage.Modality; +import org.jackhuang.hmcl.auth.microsoft.MicrosoftService; +import org.jackhuang.hmcl.ui.WebStage; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Predicate; + +public class MicrosoftAccountLoginStage extends WebStage implements MicrosoftService.WebViewCallback { + public static final MicrosoftAccountLoginStage INSTANCE = new MicrosoftAccountLoginStage(); + + CompletableFuture future; + Predicate urlTester; + + public MicrosoftAccountLoginStage() { + super(600, 600); + initModality(Modality.APPLICATION_MODAL); + + webEngine.locationProperty().addListener((observable, oldValue, newValue) -> { + if (urlTester != null && urlTester.test(newValue)) { + future.complete(newValue); + hide(); + } + }); + + showingProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + if (future != null) { + future.completeExceptionally(new InterruptedException()); + } + future = null; + urlTester = null; + } + }); + } + + @Override + public CompletableFuture show(MicrosoftService service, Predicate urlTester, String initialURL) { + Platform.runLater(() -> { + webEngine.load(initialURL); + show(); + }); + this.future = new CompletableFuture<>(); + this.urlTester = urlTester; + return future; + } +} diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml index ccc5290b3a..c274631a3f 100644 --- a/HMCL/src/main/resources/assets/fxml/account-add.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -45,7 +45,7 @@ -

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 dNilK1lhAzhv=Y^Ejs6 Date: Mon, 18 Mar 2019 20:14:31 +0800 Subject: [PATCH 0065/2639] Disable mod pane when Forge/Liteloader is not installed. --- .../hmcl/ui/versions/ModListPage.java | 19 ++++++++++++++++++- .../hmcl/ui/versions/ModListPageSkin.java | 15 ++++++++++++++- HMCL/src/main/resources/assets/css/root.css | 11 +++++++---- .../assets/fxml/download/versions.fxml | 8 ++++---- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 7 files changed, 46 insertions(+), 10 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 6d6d2791ed..85e15b849b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -28,6 +28,7 @@ import javafx.scene.control.Skin; import javafx.scene.control.TreeItem; import javafx.stage.FileChooser; +import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.mod.ModInfo; import org.jackhuang.hmcl.mod.ModManager; import org.jackhuang.hmcl.setting.Profile; @@ -52,9 +53,11 @@ public final class ModListPage extends Control { private final ListProperty items = new SimpleListProperty<>(this, "items", FXCollections.observableArrayList()); private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading", false); + private final BooleanProperty modded = new SimpleBooleanProperty(this, "modded", false); private JFXTabPane parentTab; private ModManager modManager; + private LibraryAnalyzer libraryAnalyzer; public ModListPage() { @@ -80,10 +83,12 @@ public void refresh() { } public void loadVersion(Profile profile, String id) { + libraryAnalyzer = LibraryAnalyzer.analyze(profile.getRepository().getResolvedVersion(id)); + modded.set(libraryAnalyzer.hasForge() || libraryAnalyzer.hasLiteLoader()); loadMods(profile.getRepository().getModManager(id)); } - public void loadMods(ModManager modManager) { + private void loadMods(ModManager modManager) { this.modManager = modManager; Task.ofResult(() -> { synchronized (ModListPage.this) { @@ -187,4 +192,16 @@ public void setLoading(boolean loading) { public BooleanProperty loadingProperty() { return loading; } + + public boolean isModded() { + return modded.get(); + } + + public BooleanProperty moddedProperty() { + return modded; + } + + public void setModded(boolean modded) { + this.modded.set(modded); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index f247f61493..d69c67c232 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -30,9 +30,11 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; +import javafx.scene.text.TextAlignment; import javafx.util.Callback; import org.jackhuang.hmcl.mod.ModInfo; import org.jackhuang.hmcl.setting.Theme; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.ui.construct.JFXCheckBoxTreeTableCell; import org.jackhuang.hmcl.ui.construct.SpinnerPane; @@ -53,6 +55,9 @@ private static Node wrap(Node node) { public ModListPageSkin(ModListPage skinnable) { super(skinnable); + StackPane pane = new StackPane(); + pane.getStyleClass().addAll("notice-pane", "white-background"); + BorderPane root = new BorderPane(); JFXTreeTableView tableView = new JFXTreeTableView<>(); @@ -140,7 +145,15 @@ public ModListPageSkin(ModListPage skinnable) { root.setCenter(center); } - getChildren().setAll(root); + Label label = new Label(i18n("mods.not_modded")); + label.prefWidthProperty().bind(pane.widthProperty().add(-100)); + + FXUtils.onChangeAndOperate(skinnable.moddedProperty(), modded -> { + if (modded) pane.getChildren().setAll(root); + else pane.getChildren().setAll(label); + }); + + getChildren().setAll(pane); } private void setupCellValueFactory(JFXTreeTableColumn column, Function> mapper) { diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index a6ef08dbae..6f36ecd0ef 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -57,8 +57,11 @@ -fx-text-fill: -fx-base-text-fill; } -.rippler-container= .label { - -fx-text-fill: white; +.notice-pane > .label { + -fx-text-fill: #0079FF; + -fx-font-size: 20; + -fx-wrap-text: true; + -fx-text-alignment: CENTER; } .class-title { @@ -1010,7 +1013,7 @@ } .white-background { - -fx-background-color: rgba(255, 255, 255); + -fx-background-color: rgb(255, 255, 255); } /******************************************************************************* @@ -1115,7 +1118,7 @@ } .tree-table-row-group { - -fx-background-color: rgba(230, 230, 230); + -fx-background-color: rgb(230, 230, 230); } .tree-table-view .menu-item:focused { diff --git a/HMCL/src/main/resources/assets/fxml/download/versions.fxml b/HMCL/src/main/resources/assets/fxml/download/versions.fxml index c49f0444bc..201c2230a2 100644 --- a/HMCL/src/main/resources/assets/fxml/download/versions.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/versions.fxml @@ -24,11 +24,11 @@ - -

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�`0G?zyoc6e4D-j|U6PSUEww%+9y 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 WUDhThA@xG)%~*wR5-dOlZSp@&p%zF0 delta 415783 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%0A2ElPjj(%^j?*ODO(!H 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�$ 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%0DEjG9WfH6!+W3f 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