Support fabric auto-installation
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download;
|
||||
|
||||
import org.jackhuang.hmcl.download.fabric.FabricVersionList;
|
||||
import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList;
|
||||
import org.jackhuang.hmcl.download.game.GameVersionList;
|
||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderBMCLVersionList;
|
||||
@@ -43,6 +44,8 @@ public class BMCLAPIDownloadProvider implements DownloadProvider {
|
||||
switch (id) {
|
||||
case "game":
|
||||
return GameVersionList.INSTANCE;
|
||||
case "fabric":
|
||||
return FabricVersionList.INSTANCE;
|
||||
case "forge":
|
||||
return ForgeBMCLVersionList.INSTANCE;
|
||||
case "liteloader":
|
||||
|
||||
@@ -18,14 +18,10 @@
|
||||
package org.jackhuang.hmcl.download;
|
||||
|
||||
import org.jackhuang.hmcl.download.forge.ForgeInstallTask;
|
||||
import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
|
||||
import org.jackhuang.hmcl.download.game.GameDownloadTask;
|
||||
import org.jackhuang.hmcl.download.game.GameLibrariesTask;
|
||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask;
|
||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask;
|
||||
import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
@@ -93,30 +89,21 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) {
|
||||
if (version.isResolved()) throw new IllegalArgumentException("Version should not be resolved");
|
||||
public Task<Version> installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion) {
|
||||
if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved");
|
||||
|
||||
VersionList<?> versionList = getVersionList(libraryId);
|
||||
return versionList.loadAsync(gameVersion, getDownloadProvider())
|
||||
.thenComposeAsync(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion)
|
||||
.thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion)
|
||||
.orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) {
|
||||
if (oldVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved");
|
||||
public Task<Version> installLibraryAsync(Version baseVersion, RemoteVersion libraryVersion) {
|
||||
if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved");
|
||||
|
||||
Task<Version> task;
|
||||
if (libraryVersion instanceof ForgeRemoteVersion)
|
||||
task = new ForgeInstallTask(this, oldVersion, (ForgeRemoteVersion) libraryVersion);
|
||||
else if (libraryVersion instanceof LiteLoaderRemoteVersion)
|
||||
task = new LiteLoaderInstallTask(this, oldVersion, (LiteLoaderRemoteVersion) libraryVersion);
|
||||
else if (libraryVersion instanceof OptiFineRemoteVersion)
|
||||
task = new OptiFineInstallTask(this, oldVersion, (OptiFineRemoteVersion) libraryVersion);
|
||||
else
|
||||
throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized.");
|
||||
return task
|
||||
.thenApplyAsync(oldVersion::addPatch)
|
||||
return libraryVersion.getInstallTask(this, baseVersion)
|
||||
.thenApplyAsync(baseVersion::addPatch)
|
||||
.thenComposeAsync(repository::save);
|
||||
}
|
||||
|
||||
@@ -163,19 +150,19 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
switch (libraryId) {
|
||||
case "forge":
|
||||
analyzer.ifPresent(LibraryAnalyzer.LibraryType.FORGE, (library, libraryVersion) -> newList.remove(library));
|
||||
version = version.removePatchById("net.minecraftforge");
|
||||
version = version.removePatchById(LibraryAnalyzer.LibraryType.FORGE.getPatchId());
|
||||
break;
|
||||
case "liteloader":
|
||||
analyzer.ifPresent(LibraryAnalyzer.LibraryType.LITELOADER, (library, libraryVersion) -> newList.remove(library));
|
||||
version = version.removePatchById("com.mumfrey.liteloader");
|
||||
version = version.removePatchById(LibraryAnalyzer.LibraryType.LITELOADER.getPatchId());
|
||||
break;
|
||||
case "optifine":
|
||||
analyzer.ifPresent(LibraryAnalyzer.LibraryType.OPTIFINE, (library, libraryVersion) -> newList.remove(library));
|
||||
version = version.removePatchById("net.optifine");
|
||||
version = version.removePatchById(LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId());
|
||||
break;
|
||||
case "fabric":
|
||||
analyzer.ifPresent(LibraryAnalyzer.LibraryType.FABRIC, (library, libraryVersion) -> newList.remove(library));
|
||||
version = version.removePatchById("net.fabricmc");
|
||||
version = version.removePatchById(LibraryAnalyzer.LibraryType.FABRIC.getPatchId());
|
||||
break;
|
||||
}
|
||||
return new MaintainTask(version.setLibraries(newList));
|
||||
|
||||
@@ -26,6 +26,8 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
@@ -60,12 +62,8 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
|
||||
Task<Version> libraryTask = vanillaTask.thenSupplyAsync(() -> version);
|
||||
|
||||
if (toolVersions.containsKey("forge"))
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "forge"));
|
||||
if (toolVersions.containsKey("liteloader"))
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "liteloader"));
|
||||
if (toolVersions.containsKey("optifine"))
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "optifine"));
|
||||
for (Map.Entry<String, String> entry : toolVersions.entrySet())
|
||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue()));
|
||||
|
||||
for (RemoteVersion remoteVersion : remoteVersions)
|
||||
libraryTask = libraryTask.thenComposeAsync(dependencyManager.installLibraryAsync(remoteVersion));
|
||||
@@ -77,8 +75,8 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId) {
|
||||
return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, toolVersions.get(libraryId));
|
||||
private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) {
|
||||
return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, libraryVersion);
|
||||
}
|
||||
|
||||
protected Task<Void> downloadGameAsync(String gameVersion, Version version) {
|
||||
|
||||
@@ -66,22 +66,22 @@ public interface DependencyManager {
|
||||
* **Note**: Installing a library may change the version.json.
|
||||
*
|
||||
* @param gameVersion the Minecraft version that the library relies on.
|
||||
* @param version the version.json.
|
||||
* @param baseVersion the version.json.
|
||||
* @param libraryId the type of being installed library. i.e. "forge", "liteloader", "optifine"
|
||||
* @param libraryVersion the version of being installed library.
|
||||
* @return the task to install the specific library.
|
||||
*/
|
||||
Task<?> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion);
|
||||
Task<?> installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion);
|
||||
|
||||
/**
|
||||
* Install a library to a version.
|
||||
* **Note**: Installing a library may change the version.json.
|
||||
*
|
||||
* @param version the version.json.\
|
||||
* @param baseVersion the version.json.
|
||||
* @param libraryVersion the remote version of being installed library.
|
||||
* @return the task to install the specific library.
|
||||
*/
|
||||
Task<?> installLibraryAsync(Version version, RemoteVersion libraryVersion);
|
||||
Task<?> installLibraryAsync(Version baseVersion, RemoteVersion libraryVersion);
|
||||
|
||||
/**
|
||||
* Get registered version list.
|
||||
|
||||
@@ -84,10 +84,10 @@ public final class LibraryAnalyzer {
|
||||
}
|
||||
|
||||
public enum LibraryType {
|
||||
FORGE(true, "net.minecraftforge", Pattern.compile("net\\.minecraftforge"), Pattern.compile("forge")),
|
||||
LITELOADER(true, "com.mumfrey.liteloader", Pattern.compile("com\\.mumfrey"), Pattern.compile("liteloader")),
|
||||
OPTIFINE(false, "net.optifine", Pattern.compile("(net\\.)?optifine"), Pattern.compile(".*")),
|
||||
FABRIC(true, "net.fabricmc", Pattern.compile("net\\.fabricmc"), Pattern.compile("fabric-loader"));
|
||||
FABRIC(true, "fabric", Pattern.compile("net\\.fabricmc"), Pattern.compile("fabric-loader")),
|
||||
FORGE(true, "forge", Pattern.compile("net\\.minecraftforge"), Pattern.compile("forge")),
|
||||
LITELOADER(true, "liteloader", Pattern.compile("com\\.mumfrey"), Pattern.compile("liteloader")),
|
||||
OPTIFINE(false, "optifine", Pattern.compile("(net\\.)?optifine"), Pattern.compile("^(?!.*launchwrapper).*$"));
|
||||
|
||||
private final boolean modLoader;
|
||||
private final String patchId;
|
||||
@@ -103,5 +103,9 @@ public final class LibraryAnalyzer {
|
||||
public boolean isModLoader() {
|
||||
return modLoader;
|
||||
}
|
||||
|
||||
public String getPatchId() {
|
||||
return patchId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public class MaintainTask extends Task<Version> {
|
||||
} else {
|
||||
// Vanilla Minecraft does not need maintain
|
||||
// Forge 1.13 support not implemented, not compatible with OptiFine currently.
|
||||
// Fabric does not need maintain, nothing compatible with fabric now.
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download;
|
||||
|
||||
import org.jackhuang.hmcl.download.fabric.FabricVersionList;
|
||||
import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList;
|
||||
import org.jackhuang.hmcl.download.game.GameVersionList;
|
||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderVersionList;
|
||||
@@ -43,6 +44,8 @@ public class MojangDownloadProvider implements DownloadProvider {
|
||||
switch (id) {
|
||||
case "game":
|
||||
return GameVersionList.INSTANCE;
|
||||
case "fabric":
|
||||
return FabricVersionList.INSTANCE;
|
||||
case "forge":
|
||||
return ForgeBMCLVersionList.INSTANCE;
|
||||
case "liteloader":
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download;
|
||||
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.ToStringBuilder;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
|
||||
@@ -75,6 +77,10 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Task<Version> getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) {
|
||||
throw new UnsupportedOperationException(toString() + " cannot be installed yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof RemoteVersion && Objects.equals(selfVersion, ((RemoteVersion) obj).selfVersion);
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 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.download.fabric;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.GetTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <b>Note</b>: Fabric should be installed first.
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public final class FabricInstallTask extends Task<Version> {
|
||||
|
||||
private final DefaultDependencyManager dependencyManager;
|
||||
private final Version version;
|
||||
private final FabricRemoteVersion remote;
|
||||
private final GetTask launchMetaTask;
|
||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||
|
||||
public FabricInstallTask(DefaultDependencyManager dependencyManager, Version version, FabricRemoteVersion remoteVersion) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
this.version = version;
|
||||
this.remote = remoteVersion;
|
||||
|
||||
launchMetaTask = new GetTask(NetworkUtils.toURL(getLaunchMetaUrl(remote.getSelfVersion())))
|
||||
.setCacheRepository(dependencyManager.getCacheRepository());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doPreExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preExecute() {
|
||||
if (!Objects.equals("net.minecraft.client.main.Main", version.getMainClass()))
|
||||
throw new UnsupportedFabricInstallationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependents() {
|
||||
return Collections.singleton(launchMetaTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelyingOnDependencies() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws IOException {
|
||||
setResult(getPatch(JsonUtils.GSON.fromJson(launchMetaTask.getResult(), JsonObject.class), remote.getGameVersion(), remote.getSelfVersion()));
|
||||
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult()));
|
||||
}
|
||||
|
||||
private static String getLaunchMetaUrl(String loaderVersion) {
|
||||
return String.format("%s/%s/%s/%s/%3$s-%4$s.json", "https://maven.fabricmc.net/", "net/fabricmc", "fabric-loader", loaderVersion);
|
||||
}
|
||||
|
||||
private Version getPatch(JsonObject jsonObject, String gameVersion, String loaderVersion) {
|
||||
Arguments arguments = new Arguments();
|
||||
|
||||
String mainClass;
|
||||
if (!jsonObject.get("mainClass").isJsonObject()) {
|
||||
mainClass = jsonObject.get("mainClass").getAsString();
|
||||
} else {
|
||||
mainClass = jsonObject.get("mainClass").getAsJsonObject().get("client").getAsString();
|
||||
}
|
||||
|
||||
if (jsonObject.has("launchwrapper")) {
|
||||
String clientTweaker = jsonObject.get("launchwrapper").getAsJsonObject().get("tweakers").getAsJsonObject().get("client").getAsJsonArray().get(0).getAsString();
|
||||
arguments = arguments.addGameArguments("--tweakClass", clientTweaker);
|
||||
}
|
||||
|
||||
JsonObject librariesObject = jsonObject.getAsJsonObject("libraries");
|
||||
List<Library> libraries = new ArrayList<>();
|
||||
|
||||
// "common, server" is hard coded in fabric installer.
|
||||
// Don't know the purpose of ignoring client libraries.
|
||||
for (String side : new String[]{"common", "server"}) {
|
||||
for (JsonElement element : librariesObject.getAsJsonArray(side)) {
|
||||
libraries.add(JsonUtils.GSON.fromJson(element, Library.class));
|
||||
}
|
||||
}
|
||||
|
||||
libraries.add(new Library("net.fabricmc", "intermediary", gameVersion, null, "https://maven.fabricmc.net/", null));
|
||||
libraries.add(new Library("net.fabricmc", "fabric-loader", loaderVersion, null, "https://maven.fabricmc.net/", null));
|
||||
|
||||
return new Version("net.fabricmc", loaderVersion, 30000, arguments, mainClass, libraries);
|
||||
}
|
||||
|
||||
public static class UnsupportedFabricInstallationException extends UnsupportedOperationException {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 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.download.fabric;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.RemoteVersion;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
public class FabricRemoteVersion extends RemoteVersion {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param gameVersion the Minecraft version that this remote version suits.
|
||||
* @param selfVersion the version string of the remote version.
|
||||
* @param url the installer or universal jar URL.
|
||||
*/
|
||||
FabricRemoteVersion(String gameVersion, String selfVersion, String url) {
|
||||
super(gameVersion, selfVersion, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) {
|
||||
return new FabricInstallTask(dependencyManager, baseVersion, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 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.download.fabric;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||
import org.jackhuang.hmcl.download.VersionList;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
|
||||
|
||||
public static final FabricVersionList INSTANCE = new FabricVersionList();
|
||||
|
||||
private FabricVersionList() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||
return new Task<Void>() {
|
||||
@Override
|
||||
public void execute() throws IOException, XMLStreamException {
|
||||
List<String> gameVersions = getGameVersions(META_URL);
|
||||
List<String> loaderVersions = getVersions(FABRIC_MAVEN_URL, FABRIC_PACKAGE_NAME, FABRIC_JAR_NAME);
|
||||
|
||||
lock.writeLock().lock();
|
||||
|
||||
try {
|
||||
for (String gameVersion : gameVersions)
|
||||
for (String loaderVersion : loaderVersions)
|
||||
versions.put(gameVersion, new FabricRemoteVersion(gameVersion, loaderVersion, ""));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final String META_URL = "https://meta.fabricmc.net/v2/versions/game";
|
||||
private static final String FABRIC_MAVEN_URL = "https://maven.fabricmc.net/";
|
||||
private static final String FABRIC_PACKAGE_NAME = "net/fabricmc";
|
||||
private static final String FABRIC_JAR_NAME = "fabric-loader";
|
||||
|
||||
private List<String> getVersions(String mavenServerURL, String packageName, String jarName) throws IOException, XMLStreamException {
|
||||
List<String> versions = new ArrayList<>();
|
||||
URL url = new URL(mavenServerURL + packageName + "/" + jarName + "/maven-metadata.xml");
|
||||
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(url.openStream());
|
||||
|
||||
while(reader.hasNext()) {
|
||||
if (reader.next() == 1 && reader.getLocalName().equals("version")) {
|
||||
String text = reader.getElementText();
|
||||
versions.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
reader.close();
|
||||
Collections.reverse(versions);
|
||||
return versions;
|
||||
}
|
||||
|
||||
private List<String> getGameVersions(String metaUrl) throws IOException {
|
||||
String json = NetworkUtils.doGet(NetworkUtils.toURL(metaUrl));
|
||||
return JsonUtils.GSON.<ArrayList<GameVersion>>fromJson(json, new TypeToken<ArrayList<GameVersion>>() {
|
||||
}.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static class GameVersion {
|
||||
private final String version;
|
||||
private final boolean stable;
|
||||
|
||||
public GameVersion() {
|
||||
this("", false);
|
||||
}
|
||||
|
||||
public GameVersion(String version, boolean stable) {
|
||||
this.version = version;
|
||||
this.stable = stable;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean isStable() {
|
||||
return stable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.download.forge;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||
import org.jackhuang.hmcl.download.VersionMismatchException;
|
||||
import org.jackhuang.hmcl.game.GameVersion;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
@@ -80,8 +81,8 @@ public final class ForgeInstallTask extends Task<Version> {
|
||||
public void postExecute() throws Exception {
|
||||
Files.deleteIfExists(installer);
|
||||
setResult(dependency.getResult()
|
||||
.setPriority(10000)
|
||||
.setId("net.minecraftforge")
|
||||
.setPriority(30000)
|
||||
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
|
||||
.setVersion(remote.getSelfVersion()));
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
if ("net.minecraft.launchwrapper.Launch".equals(version.getMainClass()))
|
||||
if ("net.minecraft.launchwrapper.Launch".equals(version.resolve(dependencyManager.getGameRepository()).getMainClass()))
|
||||
throw new OptiFineInstallTask.UnsupportedOptiFineInstallationException();
|
||||
|
||||
Path temp = Files.createTempDirectory("forge_installer");
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download.forge;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.RemoteVersion;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
public class ForgeRemoteVersion extends RemoteVersion {
|
||||
/**
|
||||
@@ -30,4 +33,9 @@ public class ForgeRemoteVersion extends RemoteVersion {
|
||||
public ForgeRemoteVersion(String gameVersion, String selfVersion, String url) {
|
||||
super(gameVersion, selfVersion, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) {
|
||||
return new ForgeInstallTask(dependencyManager, baseVersion, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.download.liteloader;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||
import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.LibrariesDownloadInfo;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
@@ -68,9 +69,9 @@ public final class LiteLoaderInstallTask extends Task<Version> {
|
||||
new LibrariesDownloadInfo(new LibraryDownloadInfo(null, remote.getUrl()))
|
||||
);
|
||||
|
||||
setResult(new Version("com.mumfrey.liteloader",
|
||||
setResult(new Version(LibraryAnalyzer.LibraryType.LITELOADER.getPatchId(),
|
||||
remote.getSelfVersion(),
|
||||
20000,
|
||||
60000,
|
||||
new Arguments().addGameArguments("--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"),
|
||||
"net.minecraft.launchwrapper.Launch",
|
||||
Lang.merge(remote.getLibraries(), Collections.singleton(library)))
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download.liteloader;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.RemoteVersion;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -47,4 +50,8 @@ public class LiteLoaderRemoteVersion extends RemoteVersion {
|
||||
return tweakClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) {
|
||||
return new LiteLoaderInstallTask(dependencyManager, baseVersion, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.download.optifine;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||
import org.jackhuang.hmcl.download.VersionMismatchException;
|
||||
import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.GameVersion;
|
||||
@@ -97,7 +98,7 @@ public final class OptiFineInstallTask extends Task<Version> {
|
||||
public void preExecute() throws Exception {
|
||||
if (!Arrays.asList("net.minecraft.client.main.Main",
|
||||
"net.minecraft.launchwrapper.Launch")
|
||||
.contains(version.getMainClass()))
|
||||
.contains(version.resolve(dependencyManager.getGameRepository()).getMainClass()))
|
||||
throw new UnsupportedOptiFineInstallationException();
|
||||
|
||||
|
||||
@@ -156,9 +157,9 @@ public final class OptiFineInstallTask extends Task<Version> {
|
||||
}
|
||||
|
||||
setResult(new Version(
|
||||
"net.optifine",
|
||||
LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId(),
|
||||
remote.getSelfVersion(),
|
||||
30000,
|
||||
90000,
|
||||
new Arguments().addGameArguments("--tweakClass", "optifine.OptiFineTweaker"),
|
||||
"net.minecraft.launchwrapper.Launch",
|
||||
libraries
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.download.optifine;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.RemoteVersion;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -34,4 +37,9 @@ public class OptiFineRemoteVersion extends RemoteVersion {
|
||||
public String getUrl() {
|
||||
return url.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Version> getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) {
|
||||
return new OptiFineInstallTask(dependencyManager, baseVersion, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,17 +65,17 @@ public class Version implements Comparable<Version>, Validation {
|
||||
private final ReleaseType type;
|
||||
private final Date time;
|
||||
private final Date releaseTime;
|
||||
private final int minimumLauncherVersion;
|
||||
private final Integer minimumLauncherVersion;
|
||||
private final Boolean hidden;
|
||||
private final List<Version> patches;
|
||||
|
||||
private transient final boolean resolved;
|
||||
|
||||
public Version(String id, String version, int priority, Arguments arguments, String mainClass, List<Library> libraries) {
|
||||
this(false, id, version, priority, null, arguments, mainClass, null, null, null, null, libraries, null, null, null, null, null, null, 0, null, null);
|
||||
this(false, id, version, priority, null, arguments, mainClass, null, null, null, null, libraries, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, List<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, int minimumLauncherVersion, Boolean hidden, List<Version> patches) {
|
||||
public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, List<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, List<Version> patches) {
|
||||
this.resolved = resolved;
|
||||
this.id = id;
|
||||
this.version = version;
|
||||
@@ -150,7 +150,7 @@ public class Version implements Comparable<Version>, Validation {
|
||||
}
|
||||
|
||||
public int getMinimumLauncherVersion() {
|
||||
return minimumLauncherVersion;
|
||||
return minimumLauncherVersion == null ? 0 : minimumLauncherVersion;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
@@ -222,7 +222,7 @@ public class Version implements Comparable<Version>, Validation {
|
||||
type,
|
||||
time,
|
||||
releaseTime,
|
||||
Math.max(minimumLauncherVersion, parent.minimumLauncherVersion),
|
||||
Lang.merge(minimumLauncherVersion, parent.minimumLauncherVersion, Math::max),
|
||||
hidden,
|
||||
Lang.merge(parent.patches, patches));
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -95,6 +96,12 @@ public final class Lang {
|
||||
return index < 0 || index >= a.size() ? defaultValue : a.get(index);
|
||||
}
|
||||
|
||||
public static <T> T merge(T a, T b, BinaryOperator<T> operator) {
|
||||
if (a == null) return b;
|
||||
if (b == null) return a;
|
||||
return operator.apply(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two collections into one list.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user