mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-15 23:06:07 -04:00
use separate tasks for forge installer processors
This commit is contained in:
parent
7d39d00a6a
commit
9bc10fb27d
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Hello Minecraft! Launcher
|
* Hello Minecraft! Launcher
|
||||||
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -29,7 +29,8 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import org.jackhuang.hmcl.download.fabric.FabricInstallTask;
|
import org.jackhuang.hmcl.download.fabric.FabricInstallTask;
|
||||||
import org.jackhuang.hmcl.download.forge.ForgeInstallTask;
|
import org.jackhuang.hmcl.download.forge.ForgeNewInstallTask;
|
||||||
|
import org.jackhuang.hmcl.download.forge.ForgeOldInstallTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
|
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameInstallTask;
|
import org.jackhuang.hmcl.download.game.GameInstallTask;
|
||||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask;
|
import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask;
|
||||||
@ -110,7 +111,7 @@ public final class TaskListPane extends StackPane {
|
|||||||
task.setName(i18n("assets.download_all"));
|
task.setName(i18n("assets.download_all"));
|
||||||
} else if (task instanceof GameInstallTask) {
|
} else if (task instanceof GameInstallTask) {
|
||||||
task.setName(i18n("install.installer.install", i18n("install.installer.game")));
|
task.setName(i18n("install.installer.install", i18n("install.installer.game")));
|
||||||
} else if (task instanceof ForgeInstallTask) {
|
} else if (task instanceof ForgeNewInstallTask || task instanceof ForgeOldInstallTask) {
|
||||||
task.setName(i18n("install.installer.install", i18n("install.installer.forge")));
|
task.setName(i18n("install.installer.install", i18n("install.installer.forge")));
|
||||||
} else if (task instanceof LiteLoaderInstallTask) {
|
} else if (task instanceof LiteLoaderInstallTask) {
|
||||||
task.setName(i18n("install.installer.install", i18n("install.installer.liteloader")));
|
task.setName(i18n("install.installer.install", i18n("install.installer.liteloader")));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Hello Minecraft! Launcher
|
* Hello Minecraft! Launcher
|
||||||
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -60,6 +60,7 @@ public final class ForgeInstallTask extends Task<Version> {
|
|||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.remote = remoteVersion;
|
this.remote = remoteVersion;
|
||||||
|
setSignificance(TaskSignificance.MODERATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Hello Minecraft! Launcher
|
* Hello Minecraft! Launcher
|
||||||
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -20,6 +20,7 @@ package org.jackhuang.hmcl.download.forge;
|
|||||||
import org.jackhuang.hmcl.download.ArtifactMalformedException;
|
import org.jackhuang.hmcl.download.ArtifactMalformedException;
|
||||||
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.forge.ForgeNewInstallProfile.Processor;
|
||||||
import org.jackhuang.hmcl.download.game.GameLibrariesTask;
|
import org.jackhuang.hmcl.download.game.GameLibrariesTask;
|
||||||
import org.jackhuang.hmcl.game.Artifact;
|
import org.jackhuang.hmcl.game.Artifact;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@ -36,6 +37,7 @@ import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
|||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
import org.jackhuang.hmcl.util.platform.SystemUtils;
|
import org.jackhuang.hmcl.util.platform.SystemUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -45,6 +47,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.zip.ZipException;
|
import java.util.zip.ZipException;
|
||||||
@ -55,6 +58,118 @@ import static org.jackhuang.hmcl.util.Logging.LOG;
|
|||||||
|
|
||||||
public class ForgeNewInstallTask extends Task<Version> {
|
public class ForgeNewInstallTask extends Task<Version> {
|
||||||
|
|
||||||
|
private class ProcessorTask extends Task<Void> {
|
||||||
|
|
||||||
|
private Processor processor;
|
||||||
|
private Map<String, String> vars;
|
||||||
|
|
||||||
|
public ProcessorTask(@NotNull Processor processor, @NotNull Map<String, String> vars) {
|
||||||
|
this.processor = processor;
|
||||||
|
this.vars = vars;
|
||||||
|
setSignificance(TaskSignificance.MODERATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
Map<String, String> outputs = new HashMap<>();
|
||||||
|
boolean miss = false;
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : processor.getOutputs().entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
|
||||||
|
key = parseLiteral(key, vars, ExceptionalFunction.identity());
|
||||||
|
value = parseLiteral(value, vars, ExceptionalFunction.identity());
|
||||||
|
|
||||||
|
if (key == null || value == null) {
|
||||||
|
throw new ArtifactMalformedException("Invalid forge installation configuration");
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs.put(key, value);
|
||||||
|
|
||||||
|
Path artifact = Paths.get(key);
|
||||||
|
if (Files.exists(artifact)) {
|
||||||
|
String code;
|
||||||
|
try (InputStream stream = Files.newInputStream(artifact)) {
|
||||||
|
code = encodeHex(digest("SHA-1", stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(code, value)) {
|
||||||
|
Files.delete(artifact);
|
||||||
|
LOG.info("Found existing file is not valid: " + artifact);
|
||||||
|
|
||||||
|
miss = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
miss = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!processor.getOutputs().isEmpty() && !miss) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path jar = gameRepository.getArtifactFile(version, processor.getJar());
|
||||||
|
if (!Files.isRegularFile(jar))
|
||||||
|
throw new FileNotFoundException("Game processor file not found, should be downloaded in preprocess");
|
||||||
|
|
||||||
|
String mainClass;
|
||||||
|
try (JarFile jarFile = new JarFile(jar.toFile())) {
|
||||||
|
mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(mainClass))
|
||||||
|
throw new Exception("Game processor jar does not have main class " + jar);
|
||||||
|
|
||||||
|
List<String> command = new ArrayList<>();
|
||||||
|
command.add(JavaVersion.fromCurrentEnvironment().getBinary().toString());
|
||||||
|
command.add("-cp");
|
||||||
|
|
||||||
|
List<String> classpath = new ArrayList<>(processor.getClasspath().size() + 1);
|
||||||
|
for (Artifact artifact : processor.getClasspath()) {
|
||||||
|
Path file = gameRepository.getArtifactFile(version, artifact);
|
||||||
|
if (!Files.isRegularFile(file))
|
||||||
|
throw new Exception("Game processor dependency missing");
|
||||||
|
classpath.add(file.toString());
|
||||||
|
}
|
||||||
|
classpath.add(jar.toString());
|
||||||
|
command.add(String.join(OperatingSystem.PATH_SEPARATOR, classpath));
|
||||||
|
|
||||||
|
command.add(mainClass);
|
||||||
|
|
||||||
|
List<String> args = new ArrayList<>(processor.getArgs().size());
|
||||||
|
for (String arg : processor.getArgs()) {
|
||||||
|
String parsed = parseLiteral(arg, vars, ExceptionalFunction.identity());
|
||||||
|
if (parsed == null)
|
||||||
|
throw new ArtifactMalformedException("Invalid forge installation configuration");
|
||||||
|
args.add(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
command.addAll(args);
|
||||||
|
|
||||||
|
LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
|
||||||
|
int exitCode = SystemUtils.callExternalProcess(command);
|
||||||
|
if (exitCode != 0)
|
||||||
|
throw new IOException("Game processor exited abnormally with code " + exitCode);
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : outputs.entrySet()) {
|
||||||
|
Path artifact = Paths.get(entry.getKey());
|
||||||
|
if (!Files.isRegularFile(artifact))
|
||||||
|
throw new FileNotFoundException("File missing: " + artifact);
|
||||||
|
|
||||||
|
String code;
|
||||||
|
try (InputStream stream = Files.newInputStream(artifact)) {
|
||||||
|
code = encodeHex(digest("SHA-1", stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(code, entry.getValue())) {
|
||||||
|
Files.delete(artifact);
|
||||||
|
throw new ChecksumMismatchException("SHA-1", entry.getValue(), code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final DefaultGameRepository gameRepository;
|
private final DefaultGameRepository gameRepository;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
@ -63,9 +178,13 @@ public class ForgeNewInstallTask extends Task<Version> {
|
|||||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
private ForgeNewInstallProfile profile;
|
private ForgeNewInstallProfile profile;
|
||||||
|
private List<Processor> processors;
|
||||||
private Version forgeVersion;
|
private Version forgeVersion;
|
||||||
private final String selfVersion;
|
private final String selfVersion;
|
||||||
|
|
||||||
|
private Path tempDir;
|
||||||
|
private AtomicInteger processorDoneCount = new AtomicInteger(0);
|
||||||
|
|
||||||
ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, String selfVersion, Path installer) {
|
ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, String selfVersion, Path installer) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
this.gameRepository = dependencyManager.getGameRepository();
|
this.gameRepository = dependencyManager.getGameRepository();
|
||||||
@ -73,7 +192,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
|||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
this.selfVersion = selfVersion;
|
this.selfVersion = selfVersion;
|
||||||
|
|
||||||
setSignificance(TaskSignificance.MINOR);
|
setSignificance(TaskSignificance.MAJOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String replaceTokens(Map<String, String> tokens, String value) {
|
private static String replaceTokens(Map<String, String> tokens, String value) {
|
||||||
@ -150,6 +269,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
|||||||
public void preExecute() throws Exception {
|
public void preExecute() throws Exception {
|
||||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
|
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
|
||||||
profile = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath("install_profile.json")), ForgeNewInstallProfile.class);
|
profile = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath("install_profile.json")), ForgeNewInstallProfile.class);
|
||||||
|
processors = profile.getProcessors();
|
||||||
forgeVersion = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath(profile.getJson())), Version.class);
|
forgeVersion = JsonUtils.fromNonNullJson(FileUtils.readText(fs.getPath(profile.getJson())), Version.class);
|
||||||
|
|
||||||
for (Library library : profile.getLibraries()) {
|
for (Library library : profile.getLibraries()) {
|
||||||
@ -167,151 +287,74 @@ public class ForgeNewInstallTask extends Task<Version> {
|
|||||||
FileUtils.copyFile(mainJar, dest);
|
FileUtils.copyFile(mainJar, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ZipException ex) {
|
||||||
|
throw new ArtifactMalformedException("Malformed forge installer file", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
dependents.add(new GameLibrariesTask(dependencyManager, version, true, profile.getLibraries()));
|
dependents.add(new GameLibrariesTask(dependencyManager, version, true, profile.getLibraries()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task<?> createProcessorTask(Processor processor, Map<String, String> vars) {
|
||||||
|
Task<?> task = new ProcessorTask(processor, vars);
|
||||||
|
task.onDone().register(
|
||||||
|
() -> updateProgress(processorDoneCount.incrementAndGet(), processors.size()));
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws Exception {
|
public void execute() throws Exception {
|
||||||
Path temp = Files.createTempDirectory("forge_installer");
|
tempDir = Files.createTempDirectory("forge_installer");
|
||||||
int finished = 0;
|
|
||||||
|
Map<String, String> vars = new HashMap<>();
|
||||||
|
|
||||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
|
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
|
||||||
List<ForgeNewInstallProfile.Processor> processors = profile.getProcessors();
|
for (Map.Entry<String, String> entry : profile.getData().entrySet()) {
|
||||||
Map<String, String> data = profile.getData();
|
|
||||||
|
|
||||||
updateProgress(0, processors.size());
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : data.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
String value = entry.getValue();
|
String value = entry.getValue();
|
||||||
|
|
||||||
data.put(key, parseLiteral(value,
|
vars.put(key, parseLiteral(value,
|
||||||
Collections.emptyMap(),
|
Collections.emptyMap(),
|
||||||
str -> {
|
str -> {
|
||||||
Path dest = Files.createTempFile(temp, null, null);
|
Path dest = Files.createTempFile(tempDir, null, null);
|
||||||
FileUtils.copyFile(fs.getPath(str), dest);
|
FileUtils.copyFile(fs.getPath(str), dest);
|
||||||
return dest.toString();
|
return dest.toString();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
data.put("SIDE", "client");
|
|
||||||
data.put("MINECRAFT_JAR", gameRepository.getVersionJar(version).getAbsolutePath());
|
|
||||||
data.put("MINECRAFT_VERSION", gameRepository.getVersionJar(version).getAbsolutePath());
|
|
||||||
data.put("ROOT", gameRepository.getBaseDirectory().getAbsolutePath());
|
|
||||||
data.put("INSTALLER", installer.toAbsolutePath().toString());
|
|
||||||
data.put("LIBRARY_DIR", gameRepository.getLibrariesDirectory(version).getAbsolutePath());
|
|
||||||
|
|
||||||
for (ForgeNewInstallProfile.Processor processor : processors) {
|
|
||||||
Map<String, String> outputs = new HashMap<>();
|
|
||||||
boolean miss = false;
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : processor.getOutputs().entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
String value = entry.getValue();
|
|
||||||
|
|
||||||
key = parseLiteral(key, data, ExceptionalFunction.identity());
|
|
||||||
value = parseLiteral(value, data, ExceptionalFunction.identity());
|
|
||||||
|
|
||||||
if (key == null || value == null) {
|
|
||||||
throw new ArtifactMalformedException("Invalid forge installation configuration");
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs.put(key, value);
|
|
||||||
|
|
||||||
Path artifact = Paths.get(key);
|
|
||||||
if (Files.exists(artifact)) {
|
|
||||||
String code;
|
|
||||||
try (InputStream stream = Files.newInputStream(artifact)) {
|
|
||||||
code = encodeHex(digest("SHA-1", stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Objects.equals(code, value)) {
|
|
||||||
Files.delete(artifact);
|
|
||||||
LOG.info("Found existing file is not valid: " + artifact);
|
|
||||||
|
|
||||||
miss = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
miss = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processor.getOutputs().isEmpty() && !miss) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path jar = gameRepository.getArtifactFile(version, processor.getJar());
|
|
||||||
if (!Files.isRegularFile(jar))
|
|
||||||
throw new FileNotFoundException("Game processor file not found, should be downloaded in preprocess");
|
|
||||||
|
|
||||||
String mainClass;
|
|
||||||
try (JarFile jarFile = new JarFile(jar.toFile())) {
|
|
||||||
mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(mainClass))
|
|
||||||
throw new Exception("Game processor jar does not have main class " + jar);
|
|
||||||
|
|
||||||
List<String> command = new ArrayList<>();
|
|
||||||
command.add(JavaVersion.fromCurrentEnvironment().getBinary().toString());
|
|
||||||
command.add("-cp");
|
|
||||||
|
|
||||||
List<String> classpath = new ArrayList<>(processor.getClasspath().size() + 1);
|
|
||||||
for (Artifact artifact : processor.getClasspath()) {
|
|
||||||
Path file = gameRepository.getArtifactFile(version, artifact);
|
|
||||||
if (!Files.isRegularFile(file))
|
|
||||||
throw new Exception("Game processor dependency missing");
|
|
||||||
classpath.add(file.toString());
|
|
||||||
}
|
|
||||||
classpath.add(jar.toString());
|
|
||||||
command.add(String.join(OperatingSystem.PATH_SEPARATOR, classpath));
|
|
||||||
|
|
||||||
command.add(mainClass);
|
|
||||||
|
|
||||||
List<String> args = new ArrayList<>(processor.getArgs().size());
|
|
||||||
for (String arg : processor.getArgs()) {
|
|
||||||
String parsed = parseLiteral(arg, data, ExceptionalFunction.identity());
|
|
||||||
if (parsed == null)
|
|
||||||
throw new ArtifactMalformedException("Invalid forge installation configuration");
|
|
||||||
args.add(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
command.addAll(args);
|
|
||||||
|
|
||||||
LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
|
|
||||||
int exitCode = SystemUtils.callExternalProcess(command);
|
|
||||||
if (exitCode != 0)
|
|
||||||
throw new IOException("Game processor exited abnormally");
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : outputs.entrySet()) {
|
|
||||||
Path artifact = Paths.get(entry.getKey());
|
|
||||||
if (!Files.isRegularFile(artifact))
|
|
||||||
throw new FileNotFoundException("File missing: " + artifact);
|
|
||||||
|
|
||||||
String code;
|
|
||||||
try (InputStream stream = Files.newInputStream(artifact)) {
|
|
||||||
code = encodeHex(digest("SHA-1", stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Objects.equals(code, entry.getValue())) {
|
|
||||||
Files.delete(artifact);
|
|
||||||
throw new ChecksumMismatchException("SHA-1", entry.getValue(), code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgress(++finished, processors.size());
|
|
||||||
}
|
|
||||||
} catch (ZipException ex) {
|
} catch (ZipException ex) {
|
||||||
throw new ArtifactMalformedException("Malformed forge installer file", ex);
|
throw new ArtifactMalformedException("Malformed forge installer file", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vars.put("SIDE", "client");
|
||||||
|
vars.put("MINECRAFT_JAR", gameRepository.getVersionJar(version).getAbsolutePath());
|
||||||
|
vars.put("MINECRAFT_VERSION", gameRepository.getVersionJar(version).getAbsolutePath());
|
||||||
|
vars.put("ROOT", gameRepository.getBaseDirectory().getAbsolutePath());
|
||||||
|
vars.put("INSTALLER", installer.toAbsolutePath().toString());
|
||||||
|
vars.put("LIBRARY_DIR", gameRepository.getLibrariesDirectory(version).getAbsolutePath());
|
||||||
|
|
||||||
|
updateProgress(0, processors.size());
|
||||||
|
|
||||||
|
Task<?> processorsTask = Task.runSequentially(
|
||||||
|
processors.stream()
|
||||||
|
.map(processor -> createProcessorTask(processor, vars))
|
||||||
|
.toArray(Task<?>[]::new));
|
||||||
|
|
||||||
|
dependencies.add(
|
||||||
|
processorsTask.thenComposeAsync(
|
||||||
|
dependencyManager.checkLibraryCompletionAsync(forgeVersion, true)));
|
||||||
|
|
||||||
setResult(forgeVersion
|
setResult(forgeVersion
|
||||||
.setPriority(30000)
|
.setPriority(30000)
|
||||||
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
|
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
|
||||||
.setVersion(selfVersion));
|
.setVersion(selfVersion));
|
||||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(forgeVersion, true));
|
}
|
||||||
|
|
||||||
FileUtils.deleteDirectory(temp.toFile());
|
@Override
|
||||||
|
public boolean doPostExecute() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postExecute() throws Exception {
|
||||||
|
FileUtils.deleteDirectory(tempDir.toFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Hello Minecraft! Launcher
|
* Hello Minecraft! Launcher
|
||||||
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -49,7 +49,7 @@ public class ForgeOldInstallTask extends Task<Version> {
|
|||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
this.selfVersion = selfVersion;
|
this.selfVersion = selfVersion;
|
||||||
|
|
||||||
setSignificance(TaskSignificance.MINOR);
|
setSignificance(TaskSignificance.MAJOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Hello Minecraft! Launcher
|
* Hello Minecraft! Launcher
|
||||||
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -902,6 +902,25 @@ public abstract class Task<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new task that runs the given tasks sequentially
|
||||||
|
* and returns the result of the last task.
|
||||||
|
*
|
||||||
|
* @param tasks tasks to run sequentially
|
||||||
|
* @return the combination of these tasks
|
||||||
|
*/
|
||||||
|
public static Task<?> runSequentially(Task<?>... tasks) {
|
||||||
|
if (tasks.length == 0) {
|
||||||
|
return new SimpleTask<>(() -> null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task<?> task = tasks[0];
|
||||||
|
for (int i = 1; i < tasks.length; i++) {
|
||||||
|
task = task.thenComposeAsync(tasks[i]);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
public enum TaskSignificance {
|
public enum TaskSignificance {
|
||||||
MAJOR,
|
MAJOR,
|
||||||
MODERATE,
|
MODERATE,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user