fix: downloading java runtime from mojang
This commit is contained in:
@@ -22,12 +22,14 @@ 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.DefaultCacheRepository;
|
||||
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.GameVerificationFixTask;
|
||||
import org.jackhuang.hmcl.download.game.LibraryDownloadException;
|
||||
import org.jackhuang.hmcl.download.java.JavaDownloadTask;
|
||||
import org.jackhuang.hmcl.launch.NotDecompressingNativesException;
|
||||
import org.jackhuang.hmcl.launch.PermissionException;
|
||||
import org.jackhuang.hmcl.launch.ProcessCreationException;
|
||||
@@ -64,6 +66,7 @@ import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
@@ -316,6 +319,20 @@ public final class LauncherHelper {
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (version.getJavaVersion() != null) {
|
||||
if (java.getParsedVersion() < version.getJavaVersion().getMajorVersion()) {
|
||||
Optional<JavaVersion> acceptableJava = JavaVersion.getJavas().stream()
|
||||
.filter(javaVersion -> javaVersion.getParsedVersion() >= version.getJavaVersion().getMajorVersion())
|
||||
.max(Comparator.comparing(JavaVersion::getVersionNumber));
|
||||
if (acceptableJava.isPresent()) {
|
||||
setting.setJavaVersion(acceptableJava.get());
|
||||
} else {
|
||||
downloadJava(version.getJavaVersion(), profile).thenAccept(x -> onAccept.run());
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Game later than 1.7.2 accepts Java 8.
|
||||
if (!flag && java.getParsedVersion() < JavaVersion.JAVA_8 && gameVersion.compareTo(VersionNumber.asVersion("1.7.2")) > 0) {
|
||||
Optional<JavaVersion> java8 = JavaVersion.getJavas().stream()
|
||||
@@ -446,6 +463,36 @@ public final class LauncherHelper {
|
||||
onAccept.run();
|
||||
}
|
||||
|
||||
private static CompletableFuture<Void> downloadJava(org.jackhuang.hmcl.game.JavaVersion javaVersion, Profile profile) {
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
|
||||
TaskExecutorDialogPane javaDownloadingPane = new TaskExecutorDialogPane(it -> {});
|
||||
|
||||
TaskExecutor executor = new JavaDownloadTask(javaVersion,
|
||||
DefaultCacheRepository.getInstance().getCacheDirectory().resolve("java"),
|
||||
profile.getDependency().getDownloadProvider()).executor(false);
|
||||
executor.addTaskListener(new TaskListener() {
|
||||
@Override
|
||||
public void onStop(boolean success, TaskExecutor executor) {
|
||||
super.onStop(success, executor);
|
||||
Platform.runLater(() -> {
|
||||
if (!success) {
|
||||
future.completeExceptionally(executor.getException());
|
||||
} else {
|
||||
future.complete(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
javaDownloadingPane.setExecutor(executor, true);
|
||||
Controllers.dialog(javaDownloadingPane);
|
||||
executor.start();
|
||||
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
private void checkExit() {
|
||||
switch (launcherVisibility) {
|
||||
case HIDE_AND_REOPEN:
|
||||
|
||||
@@ -78,6 +78,7 @@ public class BMCLAPIDownloadProvider implements DownloadProvider {
|
||||
|
||||
@Override
|
||||
public String injectURL(String baseURL) {
|
||||
if (baseURL.contains("v1/products/java-runtime")) return baseURL;
|
||||
return baseURL
|
||||
.replace("https://bmclapi2.bangbang93.com", apiRoot)
|
||||
.replace("https://launchermeta.mojang.com", apiRoot)
|
||||
|
||||
@@ -36,31 +36,31 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class JavaDownloadTask extends Task<Void> {
|
||||
private final String javaName;
|
||||
private final org.jackhuang.hmcl.game.JavaVersion javaVersion;
|
||||
private final Path rootDir;
|
||||
private final String platform;
|
||||
private String platform;
|
||||
private final Task<RemoteFiles> javaDownloadsTask;
|
||||
private JavaDownloads.JavaDownload download;
|
||||
private final List<Task<?>> dependencies = new ArrayList<>();
|
||||
|
||||
public JavaDownloadTask(String javaName, String javaVersion, Path rootDir, DownloadProvider downloadProvider) throws UnsupportedPlatformException {
|
||||
this.javaName = javaName;
|
||||
public JavaDownloadTask(org.jackhuang.hmcl.game.JavaVersion javaVersion, Path rootDir, DownloadProvider downloadProvider) {
|
||||
this.javaVersion = javaVersion;
|
||||
this.rootDir = rootDir;
|
||||
this.platform = getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new);
|
||||
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(
|
||||
"https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json")))
|
||||
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(
|
||||
"https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"))
|
||||
.thenComposeAsync(javaDownloadsJson -> {
|
||||
JavaDownloads allDownloads = JsonUtils.fromNonNullJson(javaDownloadsJson, JavaDownloads.class);
|
||||
if (!allDownloads.getDownloads().containsKey(platform)) throw new UnsupportedPlatformException();
|
||||
Map<String, List<JavaDownloads.JavaDownload>> osDownloads = allDownloads.getDownloads().get(platform);
|
||||
if (!osDownloads.containsKey(javaName)) throw new UnsupportedPlatformException();
|
||||
List<JavaDownloads.JavaDownload> candidates = osDownloads.get(javaName);
|
||||
if (!osDownloads.containsKey(javaVersion.getComponent())) throw new UnsupportedPlatformException();
|
||||
List<JavaDownloads.JavaDownload> candidates = osDownloads.get(javaVersion.getComponent());
|
||||
for (JavaDownloads.JavaDownload download : candidates) {
|
||||
if (VersionNumber.VERSION_COMPARATOR.compare(download.getVersion().getName(), javaVersion) >= 0) {
|
||||
if (VersionNumber.VERSION_COMPARATOR.compare(download.getVersion().getName(), Integer.toString(javaVersion.getMajorVersion())) >= 0) {
|
||||
this.download = download;
|
||||
return new GetTask(NetworkUtils.toURL(download.getManifest().getUrl()));
|
||||
}
|
||||
@@ -70,6 +70,16 @@ public class JavaDownloadTask extends Task<Void> {
|
||||
.thenApplyAsync(javaDownloadJson -> JsonUtils.fromNonNullJson(javaDownloadJson, RemoteFiles.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doPreExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preExecute() throws Exception {
|
||||
this.platform = getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependents() {
|
||||
return Collections.singleton(javaDownloadsTask);
|
||||
@@ -77,26 +87,34 @@ public class JavaDownloadTask extends Task<Void> {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
Path jvmDir = rootDir.resolve(javaName).resolve(platform).resolve(javaName);
|
||||
for (Map.Entry<String, RemoteFiles.RemoteFile> file : javaDownloadsTask.getResult().getFiles().entrySet()) {
|
||||
Path dest = jvmDir.resolve(file.getKey());
|
||||
if (file.getValue().getDownloads().containsKey("lzma")) {
|
||||
DownloadInfo download = file.getValue().getDownloads().get("lzma");
|
||||
File tempFile = Files.createTempFile("hmcl", "tmp").toFile();
|
||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||
dependencies.add(task.thenRunAsync(() -> {
|
||||
try {
|
||||
Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest);
|
||||
} catch (IOException e) {
|
||||
throw new ArtifactMalformedException("File " + file.getKey() + " is malformed");
|
||||
}
|
||||
}));
|
||||
} else if (file.getValue().getDownloads().containsKey("raw")) {
|
||||
DownloadInfo download = file.getValue().getDownloads().get("raw");
|
||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||
dependencies.add(task);
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
Path jvmDir = rootDir.resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent());
|
||||
for (Map.Entry<String, RemoteFiles.Remote> entry : javaDownloadsTask.getResult().getFiles().entrySet()) {
|
||||
Path dest = jvmDir.resolve(entry.getKey());
|
||||
if (entry.getValue() instanceof RemoteFiles.RemoteFile) {
|
||||
RemoteFiles.RemoteFile file = ((RemoteFiles.RemoteFile) entry.getValue());
|
||||
if (file.getDownloads().containsKey("lzma")) {
|
||||
DownloadInfo download = file.getDownloads().get("lzma");
|
||||
File tempFile = Files.createTempFile("hmcl", "tmp").toFile();
|
||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||
dependencies.add(task.thenRunAsync(() -> {
|
||||
try {
|
||||
Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest);
|
||||
} catch (IOException e) {
|
||||
throw new ArtifactMalformedException("File " + entry.getKey() + " is malformed");
|
||||
}
|
||||
}));
|
||||
} else if (file.getDownloads().containsKey("raw")) {
|
||||
DownloadInfo download = file.getDownloads().get("raw");
|
||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||
dependencies.add(task);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if (entry.getValue() instanceof RemoteFiles.RemoteDirectory) {
|
||||
Files.createDirectories(dest);
|
||||
} else if (entry.getValue() instanceof RemoteFiles.RemoteLink) {
|
||||
RemoteFiles.RemoteLink link = ((RemoteFiles.RemoteLink) entry.getValue());
|
||||
Files.createSymbolicLink(dest, Paths.get(link.getTarget()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,10 +131,14 @@ public class JavaDownloadTask extends Task<Void> {
|
||||
|
||||
@Override
|
||||
public void postExecute() throws Exception {
|
||||
FileUtils.writeText(rootDir.resolve(javaName).resolve(platform).resolve(".version").toFile(), download.getVersion().getName());
|
||||
FileUtils.writeText(rootDir.resolve(javaName).resolve(platform).resolve(javaName + ".sha1").toFile(),
|
||||
FileUtils.writeText(rootDir.resolve(javaVersion.getComponent()).resolve(platform).resolve(".version").toFile(), download.getVersion().getName());
|
||||
FileUtils.writeText(rootDir.resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent() + ".sha1").toFile(),
|
||||
javaDownloadsTask.getResult().getFiles().entrySet().stream()
|
||||
.map(entry -> entry.getKey() + " /#// " + entry.getValue().getDownloads().get("raw").getSha1() + " " + entry.getValue().getDownloads().get("raw").getSize())
|
||||
.filter(entry -> entry.getValue() instanceof RemoteFiles.RemoteFile)
|
||||
.map(entry -> {
|
||||
RemoteFiles.RemoteFile file = (RemoteFiles.RemoteFile) entry.getValue();
|
||||
return entry.getKey() + " /#// " + file.getDownloads().get("raw").getSha1() + " " + file.getDownloads().get("raw").getSize();
|
||||
})
|
||||
.collect(Collectors.joining(OperatingSystem.LINE_SEPARATOR)));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,17 @@ import org.jackhuang.hmcl.game.DownloadInfo;
|
||||
import org.jackhuang.hmcl.util.gson.JsonSubtype;
|
||||
import org.jackhuang.hmcl.util.gson.JsonType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class RemoteFiles {
|
||||
private final Map<String, RemoteFile> files;
|
||||
private final Map<String, Remote> files;
|
||||
|
||||
public RemoteFiles(Map<String, RemoteFile> files) {
|
||||
public RemoteFiles(Map<String, Remote> files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
public Map<String, RemoteFile> getFiles() {
|
||||
public Map<String, Remote> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -69,7 +70,7 @@ public class RemoteFiles {
|
||||
}
|
||||
|
||||
public Map<String, DownloadInfo> getDownloads() {
|
||||
return downloads;
|
||||
return downloads == null ? Collections.emptyMap() : downloads;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public class Version implements Comparable<Version>, Validation {
|
||||
private final AssetIndexInfo assetIndex;
|
||||
private final String assets;
|
||||
private final Integer complianceLevel;
|
||||
@Nullable
|
||||
private final JavaVersion javaVersion;
|
||||
private final List<Library> libraries;
|
||||
private final List<CompatibilityRule> compatibilityRules;
|
||||
@@ -80,9 +81,10 @@ public class Version implements Comparable<Version>, Validation {
|
||||
|
||||
/**
|
||||
* Constructor for patch
|
||||
* @param id patch id
|
||||
* @param version patch version
|
||||
* @param priority patch priority
|
||||
*
|
||||
* @param id patch id
|
||||
* @param version patch version
|
||||
* @param priority patch priority
|
||||
* @param arguments patch additional arguments
|
||||
* @param mainClass main class to override
|
||||
* @param libraries additional libraries
|
||||
@@ -172,11 +174,21 @@ public class Version implements Comparable<Version>, Validation {
|
||||
return minimumLauncherVersion == null ? 0 : minimumLauncherVersion;
|
||||
}
|
||||
|
||||
public Integer getComplianceLevel() {
|
||||
return complianceLevel;
|
||||
}
|
||||
|
||||
public JavaVersion getJavaVersion() {
|
||||
return javaVersion;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return hidden == null ? false : hidden;
|
||||
}
|
||||
|
||||
public boolean isRoot() { return root == null ? false : root; }
|
||||
public boolean isRoot() {
|
||||
return root == null ? false : root;
|
||||
}
|
||||
|
||||
public boolean isResolved() {
|
||||
return resolved;
|
||||
@@ -391,7 +403,7 @@ public class Version implements Comparable<Version>, Validation {
|
||||
}
|
||||
|
||||
public Version clearPatches() {
|
||||
return new Version(resolved, id, version, priority, minecraftArguments, arguments, mainClass, inheritsFrom, jar, assetIndex, assets, complianceLevel, javaVersion, libraries, compatibilityRules, downloads, logging, type, time, releaseTime, minimumLauncherVersion, hidden, root,null);
|
||||
return new Version(resolved, id, version, priority, minecraftArguments, arguments, mainClass, inheritsFrom, jar, assetIndex, assets, complianceLevel, javaVersion, libraries, compatibilityRules, downloads, logging, type, time, releaseTime, minimumLauncherVersion, hidden, root, null);
|
||||
}
|
||||
|
||||
public Version removePatchById(String patchId) {
|
||||
|
||||
@@ -127,10 +127,7 @@ public enum Architecture {
|
||||
}
|
||||
|
||||
static {
|
||||
String arch = System.getProperty("sun.arch.data.model");
|
||||
if (arch == null)
|
||||
arch = System.getProperty("os.arch");
|
||||
SYSTEM_ARCHITECTURE = arch;
|
||||
SYSTEM_ARCHITECTURE = System.getProperty("os.arch");
|
||||
|
||||
CURRENT = normalizeArch(SYSTEM_ARCHITECTURE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user