将 authlib-injector 嵌入启动器 (#4246)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -37,6 +37,8 @@ val launcherExe = System.getenv("HMCL_LAUNCHER_EXE")
|
|||||||
|
|
||||||
version = "$versionRoot.$buildNumber"
|
version = "$versionRoot.$buildNumber"
|
||||||
|
|
||||||
|
val embedResources by configurations.registering
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":HMCLCore"))
|
implementation(project(":HMCLCore"))
|
||||||
implementation(project(":HMCLBoot"))
|
implementation(project(":HMCLBoot"))
|
||||||
@@ -47,6 +49,8 @@ dependencies {
|
|||||||
if (launcherExe == null) {
|
if (launcherExe == null) {
|
||||||
implementation(libs.hmclauncher)
|
implementation(libs.hmclauncher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
embedResources(libs.authlib.injector)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getInstance(algorithm).digest(bytes)
|
fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getInstance(algorithm).digest(bytes)
|
||||||
@@ -132,6 +136,10 @@ tasks.shadowJar {
|
|||||||
exclude(project(":HMCLBoot"))
|
exclude(project(":HMCLBoot"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
into("assets/") {
|
||||||
|
from(embedResources)
|
||||||
|
}
|
||||||
|
|
||||||
manifest {
|
manifest {
|
||||||
attributes(
|
attributes(
|
||||||
"Created-By" to "Copyright(c) 2013-2025 huangyuhui.",
|
"Created-By" to "Copyright(c) 2013-2025 huangyuhui.",
|
||||||
@@ -141,6 +149,7 @@ tasks.shadowJar {
|
|||||||
"Microsoft-Auth-Id" to microsoftAuthId,
|
"Microsoft-Auth-Id" to microsoftAuthId,
|
||||||
"Microsoft-Auth-Secret" to microsoftAuthSecret,
|
"Microsoft-Auth-Secret" to microsoftAuthSecret,
|
||||||
"CurseForge-Api-Key" to curseForgeApiKey,
|
"CurseForge-Api-Key" to curseForgeApiKey,
|
||||||
|
"Authlib-Injector-Version" to libs.authlib.injector.get().version!!,
|
||||||
"Build-Channel" to versionType,
|
"Build-Channel" to versionType,
|
||||||
"Class-Path" to "pack200.jar",
|
"Class-Path" to "pack200.jar",
|
||||||
"Add-Opens" to listOf(
|
"Add-Opens" to listOf(
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException;
|
|||||||
import org.jackhuang.hmcl.game.OAuthServer;
|
import org.jackhuang.hmcl.game.OAuthServer;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.util.FileSaver;
|
import org.jackhuang.hmcl.util.FileSaver;
|
||||||
|
import org.jackhuang.hmcl.util.io.JarUtils;
|
||||||
import org.jackhuang.hmcl.util.skin.InvalidSkinException;
|
import org.jackhuang.hmcl.util.skin.InvalidSkinException;
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
@@ -68,18 +69,6 @@ public final class Accounts {
|
|||||||
|
|
||||||
private static final AuthlibInjectorArtifactProvider AUTHLIB_INJECTOR_DOWNLOADER = createAuthlibInjectorArtifactProvider();
|
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.warning("Failed to check update for authlib-injector", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final OAuthServer.Factory OAUTH_CALLBACK = new OAuthServer.Factory();
|
public static final OAuthServer.Factory OAUTH_CALLBACK = new OAuthServer.Factory();
|
||||||
|
|
||||||
public static final OfflineAccountFactory FACTORY_OFFLINE = new OfflineAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER);
|
public static final OfflineAccountFactory FACTORY_OFFLINE = new OfflineAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER);
|
||||||
@@ -337,8 +326,6 @@ public final class Accounts {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerAuthlibInjectorUpdateCheck();
|
|
||||||
|
|
||||||
for (AuthlibInjectorServer server : config().getAuthlibInjectorServers()) {
|
for (AuthlibInjectorServer server : config().getAuthlibInjectorServers()) {
|
||||||
if (selected instanceof AuthlibInjectorAccount && ((AuthlibInjectorAccount) selected).getServer() == server)
|
if (selected instanceof AuthlibInjectorAccount && ((AuthlibInjectorAccount) selected).getServer() == server)
|
||||||
continue;
|
continue;
|
||||||
@@ -371,24 +358,18 @@ public final class Accounts {
|
|||||||
// ==== authlib-injector ====
|
// ==== authlib-injector ====
|
||||||
private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() {
|
private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() {
|
||||||
String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location");
|
String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location");
|
||||||
if (authlibinjectorLocation == null) {
|
if (authlibinjectorLocation != null) {
|
||||||
return new AuthlibInjectorDownloader(
|
|
||||||
Metadata.DEPENDENCIES_DIRECTORY.resolve("universal").resolve("authlib-injector.jar"),
|
|
||||||
DownloadProviders::getDownloadProvider) {
|
|
||||||
@Override
|
|
||||||
public Optional<AuthlibInjectorArtifactInfo> getArtifactInfoImmediately() {
|
|
||||||
Optional<AuthlibInjectorArtifactInfo> local = super.getArtifactInfoImmediately();
|
|
||||||
if (local.isPresent()) {
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
// search authlib-injector.jar in current directory, it's used as a fallback
|
|
||||||
return parseArtifact(Metadata.CURRENT_DIRECTORY.resolve("authlib-injector.jar"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
LOG.info("Using specified authlib-injector: " + authlibinjectorLocation);
|
LOG.info("Using specified authlib-injector: " + authlibinjectorLocation);
|
||||||
return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation));
|
return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String authlibInjectorVersion = JarUtils.getManifestAttribute("Authlib-Injector-Version", null);
|
||||||
|
if (authlibInjectorVersion == null)
|
||||||
|
throw new AssertionError("Missing Authlib-Injector-Version");
|
||||||
|
|
||||||
|
String authlibInjectorFileName = "authlib-injector-" + authlibInjectorVersion + ".jar";
|
||||||
|
return new AuthlibInjectorExtractor(Accounts.class.getResource("/assets/" + authlibInjectorFileName),
|
||||||
|
Metadata.DEPENDENCIES_DIRECTORY.resolve("universal").resolve(authlibInjectorFileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) {
|
private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) {
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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<AuthlibInjectorArtifactInfo> 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<AuthlibInjectorArtifactInfo> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ twelvemonkeys = "3.12.0"
|
|||||||
jna = "5.17.0"
|
jna = "5.17.0"
|
||||||
pci-ids = "0.4.0"
|
pci-ids = "0.4.0"
|
||||||
java-info = "1.0"
|
java-info = "1.0"
|
||||||
|
authlib-injector = "1.2.5"
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
junit = "5.13.4"
|
junit = "5.13.4"
|
||||||
@@ -43,6 +44,7 @@ jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
|
|||||||
jna-platform = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" }
|
jna-platform = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" }
|
||||||
pci-ids = { module = "org.glavo:pci-ids", version.ref = "pci-ids" }
|
pci-ids = { module = "org.glavo:pci-ids", version.ref = "pci-ids" }
|
||||||
java-info = { module = "org.glavo:java-info", version.ref = "java-info" }
|
java-info = { module = "org.glavo:java-info", version.ref = "java-info" }
|
||||||
|
authlib-injector = { module = "org.glavo.hmcl:authlib-injector", version.ref = "authlib-injector" }
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||||
|
|||||||
Reference in New Issue
Block a user