add: stages of modpack installation
This commit is contained in:
@@ -102,7 +102,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
return versionList.loadAsync(gameVersion)
|
||||
.thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion)
|
||||
.orElseThrow(() -> new IOException("Remote library " + libraryId + " has no version " + libraryVersion))))
|
||||
.withStage("hmcl.install." + libraryId);
|
||||
.withStage(String.format("hmcl.install.%s:%s", libraryId, libraryVersion));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,7 +112,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
return removeLibraryAsync(baseVersion.resolvePreservingPatches(repository), libraryVersion.getLibraryId())
|
||||
.thenComposeAsync(version -> libraryVersion.getInstallTask(this, version))
|
||||
.thenApplyAsync(baseVersion::addPatch)
|
||||
.thenComposeAsync(repository::save).withStage("hmcl.install." + libraryVersion.getLibraryId());
|
||||
.thenComposeAsync(repository::save).withStage(String.format("hmcl.install.%s:%s", libraryVersion.getLibraryId(), libraryVersion.getSelfVersion()));
|
||||
}
|
||||
|
||||
public Task<Version> installLibraryAsync(Version oldVersion, Path installer) {
|
||||
|
||||
@@ -21,6 +21,8 @@ import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -47,19 +49,27 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
|
||||
@Override
|
||||
public Task<?> buildAsync() {
|
||||
List<String> stages = new ArrayList<>();
|
||||
|
||||
Task<Version> libraryTask = Task.supplyAsync(() -> new Version(name));
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "game", gameVersion));
|
||||
stages.add("hmcl.install.game:" + gameVersion);
|
||||
stages.add("hmcl.install.assets");
|
||||
|
||||
for (Map.Entry<String, String> entry : toolVersions.entrySet())
|
||||
for (Map.Entry<String, String> entry : toolVersions.entrySet()) {
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue()));
|
||||
stages.add(String.format("hmcl.install.%s:%s", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
for (RemoteVersion remoteVersion : remoteVersions)
|
||||
for (RemoteVersion remoteVersion : remoteVersions) {
|
||||
libraryTask = libraryTask.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion));
|
||||
stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion()));
|
||||
}
|
||||
|
||||
return libraryTask.whenComplete(exception -> {
|
||||
if (exception != null)
|
||||
dependencyManager.getGameRepository().removeVersionFromDisk(name);
|
||||
});
|
||||
}).withStagesHint(stages);
|
||||
}
|
||||
|
||||
private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Task to download Minecraft jar
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public final class GameDownloadTask extends Task<Void> {
|
||||
|
||||
@@ -69,11 +69,13 @@ public class GameInstallTask extends Task<Version> {
|
||||
setResult(patch);
|
||||
|
||||
Version version = new Version(this.version.getId()).addPatch(patch);
|
||||
dependencies.add(new GameDownloadTask(dependencyManager, remote.getGameVersion(), version)
|
||||
.thenComposeAsync(Task.allOf(
|
||||
dependencies.add(Task.allOf(
|
||||
new GameDownloadTask(dependencyManager, remote.getGameVersion(), version),
|
||||
Task.allOf(
|
||||
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY, true),
|
||||
new GameLibrariesTask(dependencyManager, version, true)
|
||||
).withStage("hmcl.install.assets").withComposeAsync(gameRepository.save(version))));
|
||||
).withStage("hmcl.install.assets")
|
||||
).withComposeAsync(gameRepository.save(version)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Install a downloaded CurseForge modpack.
|
||||
@@ -105,7 +106,8 @@ public final class CurseInstallTask extends Task<Void> {
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
this.config = config;
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), manifest.getOverrides(), any -> true, config));
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), manifest.getOverrides(), any -> true, config).withStage("hmcl.modpack"));
|
||||
dependents.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,8 +135,15 @@ public final class CurseInstallTask extends Task<Void> {
|
||||
File root = repository.getVersionRoot(name);
|
||||
FileUtils.writeText(new File(root, "manifest.json"), JsonUtils.GSON.toJson(manifest));
|
||||
|
||||
dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download"));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack.unzip"));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Stream.concat(
|
||||
dependents.stream().flatMap(task -> task.getStages().stream()),
|
||||
Stream.of("hmcl.modpack", "hmcl.modpack.download")
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "Curse";
|
||||
|
||||
@@ -43,6 +43,8 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -127,9 +129,9 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
|
||||
|
||||
try (FileSystem fs = CompressingUtils.readonly(zipFile.toPath()).setEncoding(modpack.getEncoding()).build()) {
|
||||
if (Files.exists(fs.getPath("/" + manifest.getName() + "/.minecraft")))
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/.minecraft", any -> true, config));
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/.minecraft", any -> true, config).withStage("hmcl.modpack"));
|
||||
else if (Files.exists(fs.getPath("/" + manifest.getName() + "/minecraft")))
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", any -> true, config));
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", any -> true, config).withStage("hmcl.modpack"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +175,15 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
|
||||
}
|
||||
|
||||
dependencies.add(repository.save(version));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Stream.concat(
|
||||
dependents.stream().flatMap(task -> task.getStages().stream()),
|
||||
Stream.of("hmcl.modpack")
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "MultiMC";
|
||||
|
||||
@@ -34,6 +34,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ServerModpackLocalInstallTask extends Task<Void> {
|
||||
|
||||
@@ -79,7 +81,7 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
|
||||
}
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/overrides", any -> true, config));
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/overrides", any -> true, config).withStage("hmcl.modpack"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +96,15 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Stream.concat(
|
||||
dependents.stream().flatMap(task -> task.getStages().stream()),
|
||||
Stream.of("hmcl.modpack")
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "Server";
|
||||
|
||||
@@ -24,6 +24,7 @@ import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import org.jackhuang.hmcl.event.EventManager;
|
||||
import org.jackhuang.hmcl.util.InvocationDispatcher;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
import org.jackhuang.hmcl.util.ReflectionHelper;
|
||||
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
|
||||
@@ -34,12 +35,15 @@ import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Disposable task.
|
||||
@@ -91,13 +95,17 @@ public abstract class Task<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* You must initialize stage in preExecute.
|
||||
* You must initialize stage in constructor.
|
||||
* @param stage the stage
|
||||
*/
|
||||
final void setStage(String stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
public List<String> getStages() {
|
||||
return getStage() == null ? Collections.emptyList() : Collections.singletonList(getStage());
|
||||
}
|
||||
|
||||
// state
|
||||
private TaskState state = TaskState.READY;
|
||||
|
||||
@@ -688,6 +696,11 @@ public abstract class Task<T> {
|
||||
public boolean isRelyingOnDependents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Lang.merge(Task.this.getStages(), super.getStages());
|
||||
}
|
||||
}.setExecutor(executor).setName(getCaller());
|
||||
}
|
||||
|
||||
@@ -763,11 +776,31 @@ public abstract class Task<T> {
|
||||
}
|
||||
|
||||
public Task<T> withStage(String stage) {
|
||||
StageTask<T> task = new StageTask<>(this);
|
||||
StageTask task = new StageTask();
|
||||
task.setStage(stage);
|
||||
return task;
|
||||
}
|
||||
|
||||
public Task<T> withStagesHint(List<String> stages) {
|
||||
return new Task<T>() {
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependents() {
|
||||
return Collections.singleton(Task.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
setResult(Task.this.getResult());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return stages;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Task<Void> runAsync(ExceptionalRunnable<?> closure) {
|
||||
return runAsync(Schedulers.defaultScheduler(), closure);
|
||||
}
|
||||
@@ -803,6 +836,11 @@ public abstract class Task<T> {
|
||||
public Collection<Task<?>> getDependencies() {
|
||||
return then == null ? Collections.emptySet() : Collections.singleton(then);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Lang.merge(super.getStages(), then == null ? null : then.getStages());
|
||||
}
|
||||
}.setName(name);
|
||||
}
|
||||
|
||||
@@ -862,6 +900,11 @@ public abstract class Task<T> {
|
||||
public Collection<Task<?>> getDependents() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return tasks.stream().flatMap(task -> task.getStages().stream()).collect(Collectors.toList());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -929,6 +972,11 @@ public abstract class Task<T> {
|
||||
public void execute() throws Exception {
|
||||
setResult(callable.apply(Task.this.getResult()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Lang.merge(Task.this.getStages(), super.getStages());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -988,22 +1036,30 @@ public abstract class Task<T> {
|
||||
public boolean isRelyingOnDependents() {
|
||||
return relyingOnDependents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Stream.of(Task.this.getStages(), super.getStages(), succ == null ? Collections.<String>emptyList() : succ.getStages())
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public static class StageTask<T> extends Task<T> {
|
||||
private final Task<T> task;
|
||||
StageTask(Task<T> task) {
|
||||
this.task = task;
|
||||
}
|
||||
public class StageTask extends Task<T> {
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependents() {
|
||||
return Collections.singleton(task);
|
||||
return Collections.singleton(Task.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
setResult(task.getResult());
|
||||
setResult(Task.this.getResult());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Lang.merge(Task.this.getStages(), super.getStages());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,11 @@ public abstract class TaskExecutor {
|
||||
protected final AtomicInteger totTask = new AtomicInteger(0);
|
||||
protected final AtomicBoolean cancelled = new AtomicBoolean(false);
|
||||
protected Exception exception;
|
||||
private TaskStages stages = TaskStages.EMPTY;
|
||||
private final List<String> stages;
|
||||
|
||||
public TaskExecutor(Task<?> task) {
|
||||
this.firstTask = task;
|
||||
this.stages = task.getStages();
|
||||
}
|
||||
|
||||
public void addTaskListener(TaskListener taskListener) {
|
||||
@@ -66,11 +67,7 @@ public abstract class TaskExecutor {
|
||||
return totTask.get();
|
||||
}
|
||||
|
||||
public TaskStages getStages() {
|
||||
public List<String> getStages() {
|
||||
return stages;
|
||||
}
|
||||
|
||||
public void setStages(TaskStages stages) {
|
||||
this.stages = stages;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2020 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.task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TaskStages {
|
||||
public static final TaskStages EMPTY = new TaskStages();
|
||||
|
||||
private final List<String> stages = new ArrayList<>();
|
||||
private final Map<String, String> localization = new HashMap<>();
|
||||
|
||||
protected void addStage(String stage, String localizedMessage) {
|
||||
stages.add(stage);
|
||||
localization.put(stage, localizedMessage);
|
||||
}
|
||||
|
||||
public List<String> getStages() {
|
||||
return stages;
|
||||
}
|
||||
|
||||
public String localize(String stage) {
|
||||
return localization.get(stage);
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,12 @@ public final class Lang {
|
||||
return operator.apply(a, b);
|
||||
}
|
||||
|
||||
public static <T> List<T> removingDuplicates(List<T> list) {
|
||||
LinkedHashSet<T> set = new LinkedHashSet<>(list.size());
|
||||
set.addAll(list);
|
||||
return new ArrayList<>(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two collections into one list.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user