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.Launcher;
|
||||||
import org.jackhuang.hmcl.auth.*;
|
import org.jackhuang.hmcl.auth.*;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
|
||||||
|
import org.jackhuang.hmcl.download.DefaultCacheRepository;
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.download.MaintainTask;
|
import org.jackhuang.hmcl.download.MaintainTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask;
|
import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameVerificationFixTask;
|
import org.jackhuang.hmcl.download.game.GameVerificationFixTask;
|
||||||
import org.jackhuang.hmcl.download.game.LibraryDownloadException;
|
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.NotDecompressingNativesException;
|
||||||
import org.jackhuang.hmcl.launch.PermissionException;
|
import org.jackhuang.hmcl.launch.PermissionException;
|
||||||
import org.jackhuang.hmcl.launch.ProcessCreationException;
|
import org.jackhuang.hmcl.launch.ProcessCreationException;
|
||||||
@@ -64,6 +66,7 @@ import java.io.IOException;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
@@ -316,6 +319,20 @@ public final class LauncherHelper {
|
|||||||
flag = true;
|
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.
|
// Game later than 1.7.2 accepts Java 8.
|
||||||
if (!flag && java.getParsedVersion() < JavaVersion.JAVA_8 && gameVersion.compareTo(VersionNumber.asVersion("1.7.2")) > 0) {
|
if (!flag && java.getParsedVersion() < JavaVersion.JAVA_8 && gameVersion.compareTo(VersionNumber.asVersion("1.7.2")) > 0) {
|
||||||
Optional<JavaVersion> java8 = JavaVersion.getJavas().stream()
|
Optional<JavaVersion> java8 = JavaVersion.getJavas().stream()
|
||||||
@@ -446,6 +463,36 @@ public final class LauncherHelper {
|
|||||||
onAccept.run();
|
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() {
|
private void checkExit() {
|
||||||
switch (launcherVisibility) {
|
switch (launcherVisibility) {
|
||||||
case HIDE_AND_REOPEN:
|
case HIDE_AND_REOPEN:
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class BMCLAPIDownloadProvider implements DownloadProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String injectURL(String baseURL) {
|
public String injectURL(String baseURL) {
|
||||||
|
if (baseURL.contains("v1/products/java-runtime")) return baseURL;
|
||||||
return baseURL
|
return baseURL
|
||||||
.replace("https://bmclapi2.bangbang93.com", apiRoot)
|
.replace("https://bmclapi2.bangbang93.com", apiRoot)
|
||||||
.replace("https://launchermeta.mojang.com", apiRoot)
|
.replace("https://launchermeta.mojang.com", apiRoot)
|
||||||
|
|||||||
@@ -36,31 +36,31 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class JavaDownloadTask extends Task<Void> {
|
public class JavaDownloadTask extends Task<Void> {
|
||||||
private final String javaName;
|
private final org.jackhuang.hmcl.game.JavaVersion javaVersion;
|
||||||
private final Path rootDir;
|
private final Path rootDir;
|
||||||
private final String platform;
|
private String platform;
|
||||||
private final Task<RemoteFiles> javaDownloadsTask;
|
private final Task<RemoteFiles> javaDownloadsTask;
|
||||||
private JavaDownloads.JavaDownload download;
|
private JavaDownloads.JavaDownload download;
|
||||||
private final List<Task<?>> dependencies = new ArrayList<>();
|
private final List<Task<?>> dependencies = new ArrayList<>();
|
||||||
|
|
||||||
public JavaDownloadTask(String javaName, String javaVersion, Path rootDir, DownloadProvider downloadProvider) throws UnsupportedPlatformException {
|
public JavaDownloadTask(org.jackhuang.hmcl.game.JavaVersion javaVersion, Path rootDir, DownloadProvider downloadProvider) {
|
||||||
this.javaName = javaName;
|
this.javaVersion = javaVersion;
|
||||||
this.rootDir = rootDir;
|
this.rootDir = rootDir;
|
||||||
this.platform = getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new);
|
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(
|
||||||
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(
|
"https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"))
|
||||||
"https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json")))
|
|
||||||
.thenComposeAsync(javaDownloadsJson -> {
|
.thenComposeAsync(javaDownloadsJson -> {
|
||||||
JavaDownloads allDownloads = JsonUtils.fromNonNullJson(javaDownloadsJson, JavaDownloads.class);
|
JavaDownloads allDownloads = JsonUtils.fromNonNullJson(javaDownloadsJson, JavaDownloads.class);
|
||||||
if (!allDownloads.getDownloads().containsKey(platform)) throw new UnsupportedPlatformException();
|
if (!allDownloads.getDownloads().containsKey(platform)) throw new UnsupportedPlatformException();
|
||||||
Map<String, List<JavaDownloads.JavaDownload>> osDownloads = allDownloads.getDownloads().get(platform);
|
Map<String, List<JavaDownloads.JavaDownload>> osDownloads = allDownloads.getDownloads().get(platform);
|
||||||
if (!osDownloads.containsKey(javaName)) throw new UnsupportedPlatformException();
|
if (!osDownloads.containsKey(javaVersion.getComponent())) throw new UnsupportedPlatformException();
|
||||||
List<JavaDownloads.JavaDownload> candidates = osDownloads.get(javaName);
|
List<JavaDownloads.JavaDownload> candidates = osDownloads.get(javaVersion.getComponent());
|
||||||
for (JavaDownloads.JavaDownload download : candidates) {
|
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;
|
this.download = download;
|
||||||
return new GetTask(NetworkUtils.toURL(download.getManifest().getUrl()));
|
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));
|
.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
|
@Override
|
||||||
public Collection<Task<?>> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(javaDownloadsTask);
|
return Collections.singleton(javaDownloadsTask);
|
||||||
@@ -77,26 +87,34 @@ public class JavaDownloadTask extends Task<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws Exception {
|
public void execute() throws Exception {
|
||||||
Path jvmDir = rootDir.resolve(javaName).resolve(platform).resolve(javaName);
|
Path jvmDir = rootDir.resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent());
|
||||||
for (Map.Entry<String, RemoteFiles.RemoteFile> file : javaDownloadsTask.getResult().getFiles().entrySet()) {
|
for (Map.Entry<String, RemoteFiles.Remote> entry : javaDownloadsTask.getResult().getFiles().entrySet()) {
|
||||||
Path dest = jvmDir.resolve(file.getKey());
|
Path dest = jvmDir.resolve(entry.getKey());
|
||||||
if (file.getValue().getDownloads().containsKey("lzma")) {
|
if (entry.getValue() instanceof RemoteFiles.RemoteFile) {
|
||||||
DownloadInfo download = file.getValue().getDownloads().get("lzma");
|
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();
|
File tempFile = Files.createTempFile("hmcl", "tmp").toFile();
|
||||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||||
dependencies.add(task.thenRunAsync(() -> {
|
dependencies.add(task.thenRunAsync(() -> {
|
||||||
try {
|
try {
|
||||||
Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest);
|
Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ArtifactMalformedException("File " + file.getKey() + " is malformed");
|
throw new ArtifactMalformedException("File " + entry.getKey() + " is malformed");
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} else if (file.getValue().getDownloads().containsKey("raw")) {
|
} else if (file.getDownloads().containsKey("raw")) {
|
||||||
DownloadInfo download = file.getValue().getDownloads().get("raw");
|
DownloadInfo download = file.getDownloads().get("raw");
|
||||||
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
|
||||||
dependencies.add(task);
|
dependencies.add(task);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException();
|
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
|
@Override
|
||||||
public void postExecute() throws Exception {
|
public void postExecute() throws Exception {
|
||||||
FileUtils.writeText(rootDir.resolve(javaName).resolve(platform).resolve(".version").toFile(), download.getVersion().getName());
|
FileUtils.writeText(rootDir.resolve(javaVersion.getComponent()).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(javaVersion.getComponent() + ".sha1").toFile(),
|
||||||
javaDownloadsTask.getResult().getFiles().entrySet().stream()
|
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)));
|
.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.JsonSubtype;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonType;
|
import org.jackhuang.hmcl.util.gson.JsonType;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class RemoteFiles {
|
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;
|
this.files = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, RemoteFile> getFiles() {
|
public Map<String, Remote> getFiles() {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ public class RemoteFiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, DownloadInfo> getDownloads() {
|
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 AssetIndexInfo assetIndex;
|
||||||
private final String assets;
|
private final String assets;
|
||||||
private final Integer complianceLevel;
|
private final Integer complianceLevel;
|
||||||
|
@Nullable
|
||||||
private final JavaVersion javaVersion;
|
private final JavaVersion javaVersion;
|
||||||
private final List<Library> libraries;
|
private final List<Library> libraries;
|
||||||
private final List<CompatibilityRule> compatibilityRules;
|
private final List<CompatibilityRule> compatibilityRules;
|
||||||
@@ -80,6 +81,7 @@ public class Version implements Comparable<Version>, Validation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for patch
|
* Constructor for patch
|
||||||
|
*
|
||||||
* @param id patch id
|
* @param id patch id
|
||||||
* @param version patch version
|
* @param version patch version
|
||||||
* @param priority patch priority
|
* @param priority patch priority
|
||||||
@@ -172,11 +174,21 @@ public class Version implements Comparable<Version>, Validation {
|
|||||||
return minimumLauncherVersion == null ? 0 : minimumLauncherVersion;
|
return minimumLauncherVersion == null ? 0 : minimumLauncherVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getComplianceLevel() {
|
||||||
|
return complianceLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaVersion getJavaVersion() {
|
||||||
|
return javaVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isHidden() {
|
public boolean isHidden() {
|
||||||
return hidden == null ? false : hidden;
|
return hidden == null ? false : hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRoot() { return root == null ? false : root; }
|
public boolean isRoot() {
|
||||||
|
return root == null ? false : root;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isResolved() {
|
public boolean isResolved() {
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|||||||
@@ -127,10 +127,7 @@ public enum Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String arch = System.getProperty("sun.arch.data.model");
|
SYSTEM_ARCHITECTURE = System.getProperty("os.arch");
|
||||||
if (arch == null)
|
|
||||||
arch = System.getProperty("os.arch");
|
|
||||||
SYSTEM_ARCHITECTURE = arch;
|
|
||||||
|
|
||||||
CURRENT = normalizeArch(SYSTEM_ARCHITECTURE);
|
CURRENT = normalizeArch(SYSTEM_ARCHITECTURE);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user