From af33a4f3315d01afe6bcefcb5c049269c7c70848 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Wed, 17 Dec 2025 16:57:04 -0500 Subject: [PATCH] Remove authlib-injector download code Authlib-injector is already bundled into HMCL in #4246. Due to this, `AuthlibInjectorDownloader` is no longer needed. This commit removes `AuthlibInjectorDownloader`, `AuthlibInjectorDownloadException`, `AuthlibInjectorExtractor`, `AuthlibInjectorArtifactInfo`, and `AuthlibInjectorArtifactProvider` classes, plus the `account.failed.injector_download_failure` i18n key. `AuthlibInjectorArtifactProvider` is replaced with `Supplier` to provide the jar path of authlib-injector. --- .../jackhuang/hmcl/game/LauncherHelper.java | 3 - .../org/jackhuang/hmcl/setting/Accounts.java | 59 +++++-- .../resources/assets/lang/I18N.properties | 1 - .../resources/assets/lang/I18N_ar.properties | 1 - .../resources/assets/lang/I18N_es.properties | 1 - .../resources/assets/lang/I18N_ja.properties | 1 - .../resources/assets/lang/I18N_lzh.properties | 1 - .../resources/assets/lang/I18N_ru.properties | 1 - .../resources/assets/lang/I18N_uk.properties | 1 - .../resources/assets/lang/I18N_zh.properties | 1 - .../assets/lang/I18N_zh_CN.properties | 1 - .../AuthlibInjectorAccount.java | 66 +++----- .../AuthlibInjectorAccountFactory.java | 16 +- .../AuthlibInjectorArtifactInfo.java | 79 --------- .../AuthlibInjectorArtifactProvider.java | 29 ---- .../AuthlibInjectorDownloadException.java | 41 ----- .../AuthlibInjectorDownloader.java | 160 ------------------ .../AuthlibInjectorExtractor.java | 78 --------- .../BoundAuthlibInjectorAccountFactory.java | 12 +- ...SimpleAuthlibInjectorArtifactProvider.java | 48 ------ .../hmcl/auth/offline/OfflineAccount.java | 63 ++----- .../auth/offline/OfflineAccountFactory.java | 15 +- 22 files changed, 103 insertions(+), 575 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloadException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorExtractor.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/SimpleAuthlibInjectorArtifactProvider.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 54a547f839..947614c6c9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -21,7 +21,6 @@ import javafx.stage.Stage; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.*; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.LibraryAnalyzer; @@ -291,8 +290,6 @@ public void onStop(boolean success, TaskExecutor executor) { } } else if (ex instanceof GameAssetIndexDownloadTask.GameAssetIndexMalformedException) { message = i18n("assets.index.malformed"); - } else if (ex instanceof AuthlibInjectorDownloadException) { - message = i18n("account.failed.injector_download_failure"); } else if (ex instanceof CharacterDeletedException) { message = i18n("account.failed.character_deleted"); } else if (ex instanceof ResponseCodeException) { 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 edc1d4e331..4af7a48c05 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -36,16 +36,21 @@ import org.jackhuang.hmcl.game.OAuthServer; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.FileSaver; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.JarUtils; import org.jackhuang.hmcl.util.skin.InvalidSkinException; import javax.net.ssl.SSLException; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; +import java.io.UncheckedIOException; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; +import java.util.function.Supplier; import static java.util.stream.Collectors.toList; import static javafx.collections.FXCollections.observableArrayList; @@ -67,12 +72,12 @@ public final class Accounts { private Accounts() { } - private static final AuthlibInjectorArtifactProvider AUTHLIB_INJECTOR_DOWNLOADER = createAuthlibInjectorArtifactProvider(); + private static final Supplier AUTHLIB_INJECTOR_ARTIFACT_PROVIDER = Accounts::resolveAuthlibInjectorArtifact; public static final OAuthServer.Factory OAUTH_CALLBACK = new OAuthServer.Factory(); - public static final OfflineAccountFactory FACTORY_OFFLINE = new OfflineAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER); - public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER, Accounts::getOrCreateAuthlibInjectorServer); + public static final OfflineAccountFactory FACTORY_OFFLINE = new OfflineAccountFactory(AUTHLIB_INJECTOR_ARTIFACT_PROVIDER); + public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_ARTIFACT_PROVIDER, Accounts::getOrCreateAuthlibInjectorServer); public static final MicrosoftAccountFactory FACTORY_MICROSOFT = new MicrosoftAccountFactory(new MicrosoftService(OAUTH_CALLBACK)); public static final List> FACTORIES = immutableListOf(FACTORY_OFFLINE, FACTORY_MICROSOFT, FACTORY_AUTHLIB_INJECTOR); @@ -105,7 +110,7 @@ public static AccountFactory getAccountFactory(String loginType) { } public static BoundAuthlibInjectorAccountFactory getAccountFactoryByAuthlibInjectorServer(AuthlibInjectorServer server) { - return new BoundAuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER, server); + return new BoundAuthlibInjectorAccountFactory(AUTHLIB_INJECTOR_ARTIFACT_PROVIDER, server); } // ==== @@ -356,20 +361,44 @@ public static ObjectProperty selectedAccountProperty() { } // ==== authlib-injector ==== - private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() { - String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location"); - if (authlibinjectorLocation != null) { - LOG.info("Using specified authlib-injector: " + authlibinjectorLocation); - return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation)); + private static Path resolveAuthlibInjectorArtifact() { + // 1. Use hmcl.authlibinjector.location if specified + String overrideSetting = System.getProperty("hmcl.authlibinjector.location"); + if (overrideSetting != null) { + LOG.info("Using specified authlib-injector: " + overrideSetting); + return Paths.get(overrideSetting); } - String authlibInjectorVersion = JarUtils.getAttribute("hmcl.authlib-injector.version", null); - if (authlibInjectorVersion == null) + // 2. Use bundled authlib-injector + String version = JarUtils.getAttribute("hmcl.authlib-injector.version", null); + if (version == null) throw new AssertionError("Missing hmcl.authlib-injector.version"); - String authlibInjectorFileName = "authlib-injector-" + authlibInjectorVersion + ".jar"; - return new AuthlibInjectorExtractor(Accounts.class.getResource("/assets/" + authlibInjectorFileName), - Metadata.DEPENDENCIES_DIRECTORY.resolve("universal").resolve(authlibInjectorFileName)); + String filename = "authlib-injector-" + version + ".jar"; + Path extractDir = Metadata.DEPENDENCIES_DIRECTORY.resolve("universal"); + Path extractedPath = extractDir.resolve(filename); + + if (Files.isRegularFile(extractedPath)) { + // Reuse extracted file + LOG.info("Using existing authlib-injector: " + extractedPath); + return extractedPath; + } + + // Extract bundled authlib-injector + URL bundledResource = Accounts.class.getResource("/assets/" + filename); + if (bundledResource == null) + throw new AssertionError("Missing bundled authlib-injector: " + filename); + + LOG.info("Extracting bundled authlib-injector to: " + extractedPath); + try { + Files.createDirectories(extractDir); + try (InputStream inputStream = bundledResource.openStream()) { + FileUtils.saveSafely(extractedPath, inputStream::transferTo); + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to extract bundled authlib-injector", e); + } + return extractedPath; } private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) { @@ -441,8 +470,6 @@ public static String localizeErrorMessage(Exception exception) { } } return exception.getMessage(); - } else if (exception instanceof AuthlibInjectorDownloadException) { - return i18n("account.failed.injector_download_failure"); } else if (exception instanceof CharacterDeletedException) { return i18n("account.failed.character_deleted"); } else if (exception instanceof InvalidSkinException) { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 1e18d2def9..58111b29bb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -64,7 +64,6 @@ account.failed=Failed to refresh account. account.failed.character_deleted=The player has already been deleted. account.failed.connect_authentication_server=Failed to connect to the authentication server, your network connection may be down. account.failed.connect_injector_server=Failed to connect to the authentication server. Please check your network and make sure you entered the correct URL. -account.failed.injector_download_failure=Failed to download the authlib-injector. Please check your network, or try switching to a different download source. account.failed.invalid_credentials=Incorrect password or rate limited. Please try again later. account.failed.invalid_password=Invalid password. account.failed.invalid_token=Please try logging in again. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ar.properties b/HMCL/src/main/resources/assets/lang/I18N_ar.properties index df5d2049a4..b27e9c7897 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ar.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ar.properties @@ -64,7 +64,6 @@ account.failed=فشل تحديث الحساب. account.failed.character_deleted=تم حذف اللاعب بالفعل. account.failed.connect_authentication_server=فشل الاتصال بخادم المصادقة، قد يكون اتصال الشبكة معطلاً. account.failed.connect_injector_server=فشل الاتصال بخادم المصادقة. يرجى التحقق من شبكتك والتأكد من إدخال عنوان URL الصحيح. -account.failed.injector_download_failure=فشل تنزيل authlib-injector. يرجى التحقق من شبكتك، أو محاولة التبديل إلى مصدر تنزيل مختلف. account.failed.invalid_credentials=كلمة مرور غير صحيحة أو تم تجاوز الحد المسموح. يرجى المحاولة مرة أخرى لاحقاً. account.failed.invalid_password=كلمة مرور غير صالحة. account.failed.invalid_token=يرجى المحاولة بتسجيل الدخول مرة أخرى. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index da5e1076af..888eb7dcc0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -64,7 +64,6 @@ account.failed=Error al actualizar la cuenta. account.failed.character_deleted=El jugador ya ha sido eliminado. account.failed.connect_authentication_server=No se ha podido conectar con el servidor de autenticación. Es posible que su conexión de red no funcione. account.failed.connect_injector_server=No se ha podido conectar con el servidor de autenticación. Por favor, comprueba su red y asegúrate de que has introducido la URL correcta. -account.failed.injector_download_failure=No se ha podido descargar authlib-injector. Por favor, compruebe su red, o intente cambiar a un espejo de descarga diferente. account.failed.invalid_credentials=Contraseña incorrecta o tasa limitada, por favor, inténtelo más tarde. account.failed.invalid_password=Contraseña no válida. account.failed.invalid_token=Por favor, intente iniciar sesión de nuevo. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 9de9e11139..405db71a8a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -61,7 +61,6 @@ account.failed=ログインに失敗しました account.failed.character_deleted=キャラクターが削除されました。 account.failed.connect_authentication_server=認証サーバーに接続できません。インターネット接続を確認してください。 account.failed.connect_injector_server=認証サーバーに接続できません。ネットワークをチェックして、URLが正しいことを確認してください。 -account.failed.injector_download_failure=authlib-injectorのダウンロードに失敗しました。ネットワークを確認して、別のダウンロードソースに切り替えてみてください。 account.failed.invalid_credentials=パスワードが正しくないか、一時的にログインできません。 account.failed.invalid_password=無効なパスワード account.failed.invalid_token=ログアウトし、パスワードを再入力してログインしてください。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_lzh.properties b/HMCL/src/main/resources/assets/lang/I18N_lzh.properties index 84cb8ae611..9254e0872e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_lzh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_lzh.properties @@ -63,7 +63,6 @@ account.failed=弗能新戶簿 account.failed.character_deleted=此角除訖 account.failed.connect_authentication_server=不可連所證之伺服器也,容有網謬。望查械之訪抑以代待也。\n君可求助於右上之鈕。 account.failed.connect_injector_server=不可連所證之伺服器也,容有網謬。望查械之訪與 URL 之入,抑以代待也。\n君可求助於右上之鈕。 -account.failed.injector_download_failure=無可引 authlin-injector,容有網謬。望查械之訪、試更所引之源,抑以代待也。\n君可求助於右上之鈕。 account.failed.invalid_credentials=君戶簿名、符節者有謬焉,抑入蕃而爲暫禁矣。待而復試也。 account.failed.invalid_password=無效符節 account.failed.invalid_token=望試出籍而復示符節以入 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index bfba621b2c..6bd727502d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -63,7 +63,6 @@ account.failed=Не удалось обновить аккаунт. account.failed.character_deleted=Игрок уже был удален. account.failed.connect_authentication_server=Не удалось связаться с серверами авторизации, проверьте свой интернет. account.failed.connect_injector_server=Не удалось подключиться к серверу авторизации. Проверьте свой интернет и убедитесь, что вы ввели правильный URL-адрес. -account.failed.injector_download_failure=Не удалось скачать authlib-injector. Проверьте свой интернет или попробуйте переключиться на другое зеркало скачивания. account.failed.invalid_credentials=Неверный пароль или ограничена скорость, повторите попытку позже. account.failed.invalid_password=Неверный пароль account.failed.invalid_token=Попробуйте выйти из аккаунта и повторно войти. diff --git a/HMCL/src/main/resources/assets/lang/I18N_uk.properties b/HMCL/src/main/resources/assets/lang/I18N_uk.properties index e935052b4c..4283a22f54 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_uk.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_uk.properties @@ -63,7 +63,6 @@ account.failed=Не вдалося оновити обліковий запис. account.failed.character_deleted=Гравця вже видалено. account.failed.connect_authentication_server=Не вдалося підключитися до сервера автентифікації, можливо, ваше мережеве з'єднання перервано. account.failed.connect_injector_server=Не вдалося підключитися до сервера автентифікації. Перевірте мережу та переконайтеся, що ви ввели правильну URL-адресу. -account.failed.injector_download_failure=Не вдалося завантажити authlib-injector. Перевірте мережу або спробуйте переключитися на інше джерело завантаження. account.failed.invalid_credentials=Неправильний пароль або перевищено ліміт запитів. Спробуйте пізніше. account.failed.invalid_password=Недійсний пароль. account.failed.invalid_token=Спробуйте увійти знову. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 1543239415..0bb3da0e08 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -63,7 +63,6 @@ account.failed=帳戶重新整理失敗 account.failed.character_deleted=已刪除此角色 account.failed.connect_authentication_server=無法連線至認證伺服器。可能是網路問題,請檢查裝置能否正常上網或使用代理服務。 account.failed.connect_injector_server=無法連線至認證伺服器。可能是網路故障,請檢查裝置能否正常上網、檢查網址是否輸入錯誤或使用代理服務。 -account.failed.injector_download_failure=無法下載 authlib-injector。請檢查網路或嘗試切換下載來源。 account.failed.invalid_credentials=你的使用者名稱或密碼錯誤,或者登入次數過多被暫時禁止登入。請稍後再試。 account.failed.invalid_password=密碼無效 account.failed.invalid_token=請嘗試登出並重新輸入密碼登入。 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 d0c99a620a..f8f0da6aa3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -63,7 +63,6 @@ account.failed=账户刷新失败 account.failed.character_deleted=此角色已被删除 account.failed.connect_authentication_server=无法连接认证服务器。可能是网络问题,请检查设备能否正常上网或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 account.failed.connect_injector_server=无法连接认证服务器。可能是网络问题,请检查设备是否能正常上网、URL 是否输入错误,或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 -account.failed.injector_download_failure=无法下载 authlib-injector。可能是网络问题,请检查设备是否能正常上网、尝试切换下载源或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 account.failed.invalid_credentials=你的用户名或密码错误,或登录次数过多被暂时禁止登录。请稍后再试。 account.failed.invalid_password=无效的密码 account.failed.invalid_token=请尝试登出并重新输入密码登录 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 6be37269ab..006802ebb5 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 @@ -27,10 +27,9 @@ import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; import java.io.IOException; +import java.nio.file.Path; import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutionException; +import java.util.function.Supplier; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.emptySet; @@ -38,18 +37,18 @@ public class AuthlibInjectorAccount extends YggdrasilAccount { private final AuthlibInjectorServer server; - private AuthlibInjectorArtifactProvider downloader; + private final Supplier artifactProvider; - public AuthlibInjectorAccount(AuthlibInjectorServer server, AuthlibInjectorArtifactProvider downloader, String username, String password, CharacterSelector selector) throws AuthenticationException { + public AuthlibInjectorAccount(AuthlibInjectorServer server, Supplier artifactProvider, String username, String password, CharacterSelector selector) throws AuthenticationException { super(server.getYggdrasilService(), username, password, selector); this.server = server; - this.downloader = downloader; + this.artifactProvider = artifactProvider; } - public AuthlibInjectorAccount(AuthlibInjectorServer server, AuthlibInjectorArtifactProvider downloader, String username, YggdrasilSession session) { + public AuthlibInjectorAccount(AuthlibInjectorServer server, Supplier artifactProvider, String username, YggdrasilSession session) { super(server.getYggdrasilService(), username, session); this.server = server; - this.downloader = downloader; + this.artifactProvider = artifactProvider; } @Override @@ -65,64 +64,39 @@ public synchronized AuthInfo logInWithPassword(String password) throws Authentic @Override public AuthInfo playOffline() throws AuthenticationException { AuthInfo auth = super.playOffline(); - Optional artifact = downloader.getArtifactInfoImmediately(); Optional prefetchedMeta = server.getMetadataResponse(); - if (artifact.isPresent() && prefetchedMeta.isPresent()) { - return new AuthlibInjectorAuthInfo(auth, artifact.get(), server, prefetchedMeta.get()); + if (prefetchedMeta.isPresent()) { + Path artifactPath = artifactProvider.get(); + return new AuthlibInjectorAuthInfo(auth, artifactPath, server, prefetchedMeta.get()); } else { throw new NotLoggedInException(); } } private AuthInfo inject(ExceptionalSupplier loginAction) throws AuthenticationException { - CompletableFuture prefetchedMetaTask = CompletableFuture.supplyAsync(() -> { - try { - return server.fetchMetadataResponse(); - } catch (IOException e) { - throw new CompletionException(new ServerDisconnectException(e)); - } - }); - - CompletableFuture artifactTask = CompletableFuture.supplyAsync(() -> { - try { - return downloader.getArtifactInfo(); - } catch (IOException e) { - throw new CompletionException(new AuthlibInjectorDownloadException(e)); - } - }); - - AuthInfo auth = loginAction.get(); String prefetchedMeta; - AuthlibInjectorArtifactInfo artifact; - try { - prefetchedMeta = prefetchedMetaTask.get(); - artifact = artifactTask.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new AuthenticationException(e); - } catch (ExecutionException e) { - if (e.getCause() instanceof AuthenticationException) { - throw (AuthenticationException) e.getCause(); - } else { - throw new AuthenticationException(e.getCause()); - } + prefetchedMeta = server.fetchMetadataResponse(); + } catch (IOException e) { + throw new ServerDisconnectException(e); } - return new AuthlibInjectorAuthInfo(auth, artifact, server, prefetchedMeta); + AuthInfo auth = loginAction.get(); + Path artifactPath = artifactProvider.get(); + return new AuthlibInjectorAuthInfo(auth, artifactPath, server, prefetchedMeta); } private static class AuthlibInjectorAuthInfo extends AuthInfo { - private final AuthlibInjectorArtifactInfo artifact; + private final Path artifactPath; private final AuthlibInjectorServer server; private final String prefetchedMeta; - public AuthlibInjectorAuthInfo(AuthInfo authInfo, AuthlibInjectorArtifactInfo artifact, AuthlibInjectorServer server, String prefetchedMeta) { + public AuthlibInjectorAuthInfo(AuthInfo authInfo, Path artifactPath, AuthlibInjectorServer server, String prefetchedMeta) { super(authInfo.getUsername(), authInfo.getUUID(), authInfo.getAccessToken(), authInfo.getUserType(), authInfo.getUserProperties()); - this.artifact = artifact; + this.artifactPath = artifactPath; this.server = server; this.prefetchedMeta = prefetchedMeta; } @@ -130,7 +104,7 @@ public AuthlibInjectorAuthInfo(AuthInfo authInfo, AuthlibInjectorArtifactInfo ar @Override public Arguments getLaunchArguments(LaunchOptions options) { return new Arguments().addJVMArguments( - "-javaagent:" + artifact.getLocation().toString() + "=" + server.getUrl(), + "-javaagent:" + artifactPath.toAbsolutePath() + "=" + server.getUrl(), "-Dauthlibinjector.side=client", "-Dauthlibinjector.yggdrasil.prefetched=" + Base64.getEncoder().encodeToString(prefetchedMeta.getBytes(UTF_8))); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java index dbf6d038d5..75df4b189f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java @@ -25,22 +25,24 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilSession; import org.jackhuang.hmcl.util.javafx.ObservableOptionalCache; +import java.nio.file.Path; import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.function.Function; +import java.util.function.Supplier; import static org.jackhuang.hmcl.util.Lang.tryCast; public class AuthlibInjectorAccountFactory extends AccountFactory { - private final AuthlibInjectorArtifactProvider downloader; + private final Supplier artifactProvider; private final Function serverLookup; /** * @param serverLookup a function that looks up {@link AuthlibInjectorServer} by url */ - public AuthlibInjectorAccountFactory(AuthlibInjectorArtifactProvider downloader, Function serverLookup) { - this.downloader = downloader; + public AuthlibInjectorAccountFactory(Supplier artifactProvider, Function serverLookup) { + this.artifactProvider = artifactProvider; this.serverLookup = serverLookup; } @@ -57,7 +59,7 @@ public AuthlibInjectorAccount create(CharacterSelector selector, String username AuthlibInjectorServer server = (AuthlibInjectorServer) additionalData; - return new AuthlibInjectorAccount(server, downloader, username, password, selector); + return new AuthlibInjectorAccount(server, artifactProvider, username, password, selector); } @Override @@ -67,10 +69,10 @@ public AuthlibInjectorAccount fromStorage(Map storage) { String apiRoot = tryCast(storage.get("serverBaseURL"), String.class) .orElseThrow(() -> new IllegalArgumentException("storage does not have API root.")); AuthlibInjectorServer server = serverLookup.apply(apiRoot); - return fromStorage(storage, downloader, server); + return fromStorage(storage, artifactProvider, server); } - static AuthlibInjectorAccount fromStorage(Map storage, AuthlibInjectorArtifactProvider downloader, AuthlibInjectorServer server) { + static AuthlibInjectorAccount fromStorage(Map storage, Supplier artifactProvider, AuthlibInjectorServer server) { YggdrasilSession session = YggdrasilSession.fromStorage(storage); String username = tryCast(storage.get("username"), String.class) @@ -86,6 +88,6 @@ static AuthlibInjectorAccount fromStorage(Map storage, AuthlibIn profileRepository.invalidate(selected.getId()); }); - return new AuthlibInjectorAccount(server, downloader, username, session); + return new AuthlibInjectorAccount(server, artifactProvider, username, session); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactInfo.java deleted file mode 100644 index 7fca3c3fe3..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactInfo.java +++ /dev/null @@ -1,79 +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.auth.authlibinjector; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; -import java.util.jar.Attributes; -import java.util.jar.JarFile; - -public class AuthlibInjectorArtifactInfo { - - public static AuthlibInjectorArtifactInfo from(Path location) throws IOException { - try (JarFile jarFile = new JarFile(location.toFile())) { - Attributes attributes = jarFile.getManifest().getMainAttributes(); - - String title = Optional.ofNullable(attributes.getValue("Implementation-Title")) - .orElseThrow(() -> new IOException("Missing Implementation-Title")); - if (!"authlib-injector".equals(title)) { - throw new IOException("Bad Implementation-Title"); - } - - String version = Optional.ofNullable(attributes.getValue("Implementation-Version")) - .orElseThrow(() -> new IOException("Missing Implementation-Version")); - - int buildNumber; - try { - buildNumber = Optional.ofNullable(attributes.getValue("Build-Number")) - .map(Integer::parseInt) - .orElseThrow(() -> new IOException("Missing Build-Number")); - } catch (NumberFormatException e) { - throw new IOException("Bad Build-Number", e); - } - return new AuthlibInjectorArtifactInfo(buildNumber, version, location.toAbsolutePath()); - } - } - - private int buildNumber; - private String version; - private Path location; - - public AuthlibInjectorArtifactInfo(int buildNumber, String version, Path location) { - this.buildNumber = buildNumber; - this.version = version; - this.location = location; - } - - public int getBuildNumber() { - return buildNumber; - } - - public String getVersion() { - return version; - } - - public Path getLocation() { - return location; - } - - @Override - public String toString() { - return "authlib-injector [buildNumber=" + buildNumber + ", version=" + version + "]"; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactProvider.java deleted file mode 100644 index 57520a2dce..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactProvider.java +++ /dev/null @@ -1,29 +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.auth.authlibinjector; - -import java.io.IOException; -import java.util.Optional; - -public interface AuthlibInjectorArtifactProvider { - - AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException; - - Optional getArtifactInfoImmediately(); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloadException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloadException.java deleted file mode 100644 index d5442a5fde..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloadException.java +++ /dev/null @@ -1,41 +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.auth.authlibinjector; - -import org.jackhuang.hmcl.auth.AuthenticationException; - -/** - * @author yushijinhun - */ -public class AuthlibInjectorDownloadException extends AuthenticationException { - - public AuthlibInjectorDownloadException() { - } - - public AuthlibInjectorDownloadException(String message, Throwable cause) { - super(message, cause); - } - - public AuthlibInjectorDownloadException(String message) { - super(message); - } - - public AuthlibInjectorDownloadException(Throwable cause) { - super(cause); - } -} 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 deleted file mode 100644 index 28ace53200..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorDownloader.java +++ /dev/null @@ -1,160 +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.auth.authlibinjector; - -import com.google.gson.JsonParseException; -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.task.FileDownloadTask; -import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; -import org.jackhuang.hmcl.util.io.HttpRequest; - -import java.io.IOException; -import java.net.URI; -import java.nio.file.Files; -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 static org.jackhuang.hmcl.util.logging.Logger.LOG; - -public class AuthlibInjectorDownloader implements AuthlibInjectorArtifactProvider { - - private static final String LATEST_BUILD_URL = "https://authlib-injector.yushi.moe/artifact/latest.json"; - - private final Path artifactLocation; - private final Supplier downloadProvider; - - /** - * @param artifactLocation where to save authlib-injector artifacts - */ - public AuthlibInjectorDownloader(Path artifactLocation, Supplier downloadProvider) { - this.artifactLocation = artifactLocation; - this.downloadProvider = downloadProvider; - } - - @Override - public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException { - Optional cached = getArtifactInfoImmediately(); - if (cached.isPresent()) { - return cached.get(); - } - - synchronized (this) { - Optional local = getLocalArtifact(); - if (local.isPresent()) { - return local.get(); - } - 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")); - } - } - - @Override - public Optional getArtifactInfoImmediately() { - return getLocalArtifact(); - } - - 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; - } - - try { - new FileDownloadTask(downloadProvider.get().injectURLWithCandidates(latest.downloadUrl), artifactLocation, - Optional.ofNullable(latest.checksums.get("sha256")) - .map(checksum -> new IntegrityCheck("SHA-256", checksum)) - .orElse(null)) - .run(); - } catch (Exception e) { - throw new IOException("Failed to download authlib-injector", e); - } - - LOG.info("Updated authlib-injector to " + latest.version); - } - - private AuthlibInjectorVersionInfo getLatestArtifactInfo() throws IOException { - IOException exception = null; - for (URI url : downloadProvider.get().injectURLWithCandidates(LATEST_BUILD_URL)) { - try { - return HttpRequest.GET(url.toString()).getJson(AuthlibInjectorVersionInfo.class); - } catch (IOException | JsonParseException e) { - if (exception == null) { - exception = new IOException("Failed to fetch authlib-injector artifact info"); - } - exception.addSuppressed(e); - } - } - - if (exception == null) { - exception = new IOException("No authlib-injector download providers available"); - } - throw exception; - } - - private Optional getLocalArtifact() { - return parseArtifact(artifactLocation); - } - - protected static Optional parseArtifact(Path path) { - if (!Files.isRegularFile(path)) { - return Optional.empty(); - } - try { - return Optional.of(AuthlibInjectorArtifactInfo.from(path)); - } catch (IOException e) { - LOG.warning("Bad authlib-injector artifact", e); - return Optional.empty(); - } - } - - private static final class AuthlibInjectorVersionInfo { - @SerializedName("build_number") - public int buildNumber; - - @SerializedName("version") - public String version; - - @SerializedName("download_url") - public String downloadUrl; - - @SerializedName("checksums") - public Map checksums; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorExtractor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorExtractor.java deleted file mode 100644 index 06ab1479c6..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorExtractor.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2025 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.auth.authlibinjector; - -import org.jackhuang.hmcl.util.io.FileUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Optional; - -import static org.jackhuang.hmcl.util.logging.Logger.LOG; - -/** - * @author Glavo - */ -public final class AuthlibInjectorExtractor implements AuthlibInjectorArtifactProvider { - private final URL source; - private final Path artifactLocation; - - public AuthlibInjectorExtractor(URL source, Path artifactLocation) { - if (source == null) - throw new IllegalArgumentException("Missing authlib injector"); - this.source = source; - this.artifactLocation = artifactLocation; - } - - @Override - public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException { - Optional cached = getArtifactInfoImmediately(); - if (cached.isPresent()) - return cached.get(); - - synchronized (this) { - cached = getArtifactInfoImmediately(); - if (cached.isPresent()) - return cached.get(); - - LOG.info("No local authlib-injector found, extracting"); - Files.createDirectories(artifactLocation.getParent()); - try (InputStream inputStream = source.openStream()) { - FileUtils.saveSafely(artifactLocation, inputStream::transferTo); - } - return getArtifactInfoImmediately().orElseThrow(() -> - new IOException("Failed to extract authlib-injector artifact")); - } - } - - @Override - public Optional getArtifactInfoImmediately() { - if (!Files.isRegularFile(artifactLocation)) - return Optional.empty(); - - try { - return Optional.of(AuthlibInjectorArtifactInfo.from(artifactLocation)); - } catch (IOException e) { - LOG.warning("Bad authlib-injector artifact", e); - return Optional.empty(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/BoundAuthlibInjectorAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/BoundAuthlibInjectorAccountFactory.java index bfbffe6dbc..a772859aba 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/BoundAuthlibInjectorAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/BoundAuthlibInjectorAccountFactory.java @@ -21,18 +21,20 @@ import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.CharacterSelector; +import java.nio.file.Path; import java.util.Map; import java.util.Objects; +import java.util.function.Supplier; public class BoundAuthlibInjectorAccountFactory extends AccountFactory { - private final AuthlibInjectorArtifactProvider downloader; + private final Supplier artifactProvider; private final AuthlibInjectorServer server; /** * @param server Authlib-Injector Server */ - public BoundAuthlibInjectorAccountFactory(AuthlibInjectorArtifactProvider downloader, AuthlibInjectorServer server) { - this.downloader = downloader; + public BoundAuthlibInjectorAccountFactory(Supplier artifactProvider, AuthlibInjectorServer server) { + this.artifactProvider = artifactProvider; this.server = server; } @@ -51,11 +53,11 @@ public AuthlibInjectorAccount create(CharacterSelector selector, String username Objects.requireNonNull(username); Objects.requireNonNull(password); - return new AuthlibInjectorAccount(server, downloader, username, password, selector); + return new AuthlibInjectorAccount(server, artifactProvider, username, password, selector); } @Override public AuthlibInjectorAccount fromStorage(Map storage) { - return AuthlibInjectorAccountFactory.fromStorage(storage, downloader, server); + return AuthlibInjectorAccountFactory.fromStorage(storage, artifactProvider, server); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/SimpleAuthlibInjectorArtifactProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/SimpleAuthlibInjectorArtifactProvider.java deleted file mode 100644 index f359fc6b3b..0000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/SimpleAuthlibInjectorArtifactProvider.java +++ /dev/null @@ -1,48 +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.auth.authlibinjector; - -import static org.jackhuang.hmcl.util.logging.Logger.LOG; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -public class SimpleAuthlibInjectorArtifactProvider implements AuthlibInjectorArtifactProvider { - - private Path location; - - public SimpleAuthlibInjectorArtifactProvider(Path location) { - this.location = location; - } - - @Override - public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException { - return AuthlibInjectorArtifactInfo.from(location); - } - - @Override - public Optional getArtifactInfoImmediately() { - try { - return Optional.of(getArtifactInfo()); - } catch (IOException e) { - LOG.warning("Bad authlib-injector artifact", e); - return Optional.empty(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccount.java index e6955b745f..9ae03e62b0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccount.java @@ -21,9 +21,6 @@ import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthenticationException; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactInfo; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactProvider; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException; import org.jackhuang.hmcl.auth.yggdrasil.Texture; import org.jackhuang.hmcl.auth.yggdrasil.TextureType; import org.jackhuang.hmcl.game.Arguments; @@ -33,12 +30,11 @@ import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; import java.io.IOException; +import java.nio.file.Path; import java.util.Map; import java.util.Optional; import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutionException; +import java.util.function.Supplier; import static java.util.Objects.requireNonNull; import static org.jackhuang.hmcl.util.Lang.mapOf; @@ -50,13 +46,13 @@ */ public class OfflineAccount extends Account { - private final AuthlibInjectorArtifactProvider downloader; + private final Supplier authlibInjectorArtifactProvider; private final String username; private final UUID uuid; private Skin skin; - protected OfflineAccount(AuthlibInjectorArtifactProvider downloader, String username, UUID uuid, Skin skin) { - this.downloader = requireNonNull(downloader); + protected OfflineAccount(Supplier authlibInjectorArtifactProvider, String username, UUID uuid, Skin skin) { + this.authlibInjectorArtifactProvider = requireNonNull(authlibInjectorArtifactProvider); this.username = requireNonNull(username); this.uuid = requireNonNull(uuid); this.skin = skin; @@ -66,8 +62,8 @@ protected OfflineAccount(AuthlibInjectorArtifactProvider downloader, String user } } - public AuthlibInjectorArtifactProvider getDownloader() { - return downloader; + public Supplier getAuthlibInjectorArtifactProvider() { + return authlibInjectorArtifactProvider; } @Override @@ -109,51 +105,26 @@ public AuthInfo logIn() throws AuthenticationException { AuthInfo authInfo = new AuthInfo(username, uuid, UUIDTypeAdapter.fromUUID(UUID.randomUUID()), AuthInfo.USER_TYPE_MSA, "{}"); if (loadAuthlibInjector(skin)) { - CompletableFuture artifactTask = CompletableFuture.supplyAsync(() -> { - try { - return downloader.getArtifactInfo(); - } catch (IOException e) { - throw new CompletionException(new AuthlibInjectorDownloadException(e)); - } - }); - - AuthlibInjectorArtifactInfo artifact; - try { - artifact = artifactTask.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new AuthenticationException(e); - } catch (ExecutionException e) { - if (e.getCause() instanceof AuthenticationException) { - throw (AuthenticationException) e.getCause(); - } else { - throw new AuthenticationException(e.getCause()); - } - } - - try { - return new OfflineAuthInfo(authInfo, artifact); - } catch (Exception e) { - throw new AuthenticationException(e); - } + return new OfflineAuthInfo(authInfo, authlibInjectorArtifactProvider.get()); } else { return authInfo; } } private class OfflineAuthInfo extends AuthInfo { - private final AuthlibInjectorArtifactInfo artifact; + private final Path authlibInjectorArtifact; private YggdrasilServer server; - public OfflineAuthInfo(AuthInfo authInfo, AuthlibInjectorArtifactInfo artifact) { + public OfflineAuthInfo(AuthInfo authInfo, Path authlibInjectorArtifact) { super(authInfo.getUsername(), authInfo.getUUID(), authInfo.getAccessToken(), USER_TYPE_MSA, authInfo.getUserProperties()); - this.artifact = artifact; + this.authlibInjectorArtifact = authlibInjectorArtifact; } @Override public Arguments getLaunchArguments(LaunchOptions options) throws IOException { - if (!options.isDaemon()) return null; + if (!options.isDaemon()) + return null; server = new YggdrasilServer(0); server.start(); @@ -168,9 +139,8 @@ public Arguments getLaunchArguments(LaunchOptions options) throws IOException { } return new Arguments().addJVMArguments( - "-javaagent:" + artifact.getLocation().toString() + "=" + "http://localhost:" + server.getListeningPort(), - "-Dauthlibinjector.side=client" - ); + "-javaagent:" + authlibInjectorArtifact.toAbsolutePath() + "=" + "http://localhost:" + server.getListeningPort(), + "-Dauthlibinjector.side=client"); } @Override @@ -192,8 +162,7 @@ public Map toStorage() { return mapOf( pair("uuid", UUIDTypeAdapter.fromUUID(uuid)), pair("username", username), - pair("skin", skin == null ? null : skin.toStorage()) - ); + pair("skin", skin == null ? null : skin.toStorage())); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java index e06dbdbb9e..04040e4aae 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java @@ -19,11 +19,12 @@ import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.CharacterSelector; -import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactProvider; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; +import java.nio.file.Path; import java.util.Map; import java.util.UUID; +import java.util.function.Supplier; import static java.nio.charset.StandardCharsets.UTF_8; import static org.jackhuang.hmcl.util.Lang.tryCast; @@ -33,10 +34,10 @@ * @author huangyuhui */ public final class OfflineAccountFactory extends AccountFactory { - private final AuthlibInjectorArtifactProvider downloader; + private final Supplier authlibInjectorArtifactProvider; - public OfflineAccountFactory(AuthlibInjectorArtifactProvider downloader) { - this.downloader = downloader; + public OfflineAccountFactory(Supplier authlibInjectorArtifactProvider) { + this.authlibInjectorArtifactProvider = authlibInjectorArtifactProvider; } @Override @@ -45,7 +46,7 @@ public AccountLoginType getLoginType() { } public OfflineAccount create(String username, UUID uuid) { - return new OfflineAccount(downloader, username, uuid, null); + return new OfflineAccount(authlibInjectorArtifactProvider, username, uuid, null); } @Override @@ -61,7 +62,7 @@ public OfflineAccount create(CharacterSelector selector, String username, String uuid = getUUIDFromUserName(username); skin = null; } - return new OfflineAccount(downloader, username, uuid, skin); + return new OfflineAccount(authlibInjectorArtifactProvider, username, uuid, skin); } @Override @@ -73,7 +74,7 @@ public OfflineAccount fromStorage(Map storage) { .orElse(getUUIDFromUserName(username)); Skin skin = Skin.fromStorage(tryCast(storage.get("skin"), Map.class).orElse(null)); - return new OfflineAccount(downloader, username, uuid, skin); + return new OfflineAccount(authlibInjectorArtifactProvider, username, uuid, skin); } public static UUID getUUIDFromUserName(String username) {