Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions HMCL/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ val launcherExe = System.getenv("HMCL_LAUNCHER_EXE")

version = "$versionRoot.$buildNumber"

val embedResources by configurations.registering

dependencies {
implementation(project(":HMCLCore"))
implementation(project(":HMCLBoot"))
Expand All @@ -47,6 +49,8 @@ dependencies {
if (launcherExe == null) {
implementation(libs.hmclauncher)
}

embedResources(libs.authlib.injector)
}

fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getInstance(algorithm).digest(bytes)
Expand Down Expand Up @@ -132,6 +136,10 @@ tasks.shadowJar {
exclude(project(":HMCLBoot"))
}

into("assets/") {
from(embedResources)
}

manifest {
attributes(
"Created-By" to "Copyright(c) 2013-2025 huangyuhui.",
Expand All @@ -141,6 +149,7 @@ tasks.shadowJar {
"Microsoft-Auth-Id" to microsoftAuthId,
"Microsoft-Auth-Secret" to microsoftAuthSecret,
"CurseForge-Api-Key" to curseForgeApiKey,
"Authlib-Injector-Version" to libs.authlib.injector.get().version!!,
"Build-Channel" to versionType,
"Class-Path" to "pack200.jar",
"Add-Opens" to listOf(
Expand Down
39 changes: 10 additions & 29 deletions HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.jackhuang.hmcl.game.OAuthServer;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.util.FileSaver;
import org.jackhuang.hmcl.util.io.JarUtils;
import org.jackhuang.hmcl.util.skin.InvalidSkinException;

import javax.net.ssl.SSLException;
Expand Down Expand Up @@ -68,18 +69,6 @@ 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.warning("Failed to check update for authlib-injector", e);
}
});
}
}

public static final OAuthServer.Factory OAUTH_CALLBACK = new OAuthServer.Factory();

public static final OfflineAccountFactory FACTORY_OFFLINE = new OfflineAccountFactory(AUTHLIB_INJECTOR_DOWNLOADER);
Expand Down Expand Up @@ -337,8 +326,6 @@ public void onChanged(Change<? extends Account> change) {
});
}

triggerAuthlibInjectorUpdateCheck();

for (AuthlibInjectorServer server : config().getAuthlibInjectorServers()) {
if (selected instanceof AuthlibInjectorAccount && ((AuthlibInjectorAccount) selected).getServer() == server)
continue;
Expand Down Expand Up @@ -371,24 +358,18 @@ public static ObjectProperty<Account> selectedAccountProperty() {
// ==== authlib-injector ====
private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() {
String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location");
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 {
if (authlibinjectorLocation != null) {
LOG.info("Using specified authlib-injector: " + 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");
Copy link

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message should be more descriptive about where the version should be found. Consider "Missing Authlib-Injector-Version in JAR manifest" to provide better debugging context.

Suggested change
throw new AssertionError("Missing Authlib-Injector-Version");
throw new AssertionError("Missing Authlib-Injector-Version in JAR manifest");

Copilot uses AI. Check for mistakes.

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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <[email protected]> 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");
Copy link

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message "Missing authlib injector" is not descriptive enough. Consider a more specific message like "Authlib injector source URL cannot be null" to help with debugging.

Suggested change
throw new IllegalArgumentException("Missing authlib injector");
throw new IllegalArgumentException("Authlib injector source URL cannot be null");

Copilot uses AI. Check for mistakes.
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("No local authlib-injector found"));
}
}

@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();
}
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ twelvemonkeys = "3.12.0"
jna = "5.17.0"
pci-ids = "0.4.0"
java-info = "1.0"
authlib-injector = "1.2.5"

# testing
junit = "5.13.4"
Expand Down Expand Up @@ -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" }
pci-ids = { module = "org.glavo:pci-ids", version.ref = "pci-ids" }
java-info = { module = "org.glavo:java-info", version.ref = "java-info" }
authlib-injector = { module = "org.glavo.hmcl:authlib-injector", version.ref = "authlib-injector" }

# testing
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
Expand Down