1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2025-01-23 21:51:26 +01:00

Add support for Fabric loader & expand SidedData

Also improved library handling some more
This commit is contained in:
Henry Le Grys 2020-12-03 01:17:18 +00:00
parent 69a001282c
commit 9a32ab8dc3
12 changed files with 186 additions and 17 deletions

View File

@ -19,10 +19,7 @@ import com.google.common.io.Closer;
import com.google.common.io.Files;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.LauncherUtils;
import com.skcraft.launcher.builder.loaders.ILoaderProcessor;
import com.skcraft.launcher.builder.loaders.LoaderResult;
import com.skcraft.launcher.builder.loaders.ModernForgeLoaderProcessor;
import com.skcraft.launcher.builder.loaders.OldForgeLoaderProcessor;
import com.skcraft.launcher.builder.loaders.*;
import com.skcraft.launcher.model.loader.BasicInstallProfile;
import com.skcraft.launcher.model.minecraft.Library;
import com.skcraft.launcher.model.minecraft.ReleaseList;
@ -171,6 +168,8 @@ public class PackageBuilder {
} else if (basicProfile.getProfile().equalsIgnoreCase("forge")) {
processor = new ModernForgeLoaderProcessor();
}
} else if (BuilderUtils.getZipEntry(jarFile, "fabric-installer.json") != null) {
processor = new FabricLoaderProcessor();
}
} finally {
closer.close();
@ -200,6 +199,7 @@ public class PackageBuilder {
Files.createParentDirs(outputPath);
boolean found = false;
// Try just the URL, it might be a full URL to the file
if (!artifact.getUrl().isEmpty()) {
found = tryDownloadLibrary(library, artifact, artifact.getUrl(), outputPath);
}
@ -212,6 +212,12 @@ public class PackageBuilder {
}
}
// Assume artifact URL is a maven repository URL and try that
if (!found) {
URL url = LauncherUtils.concat(url(artifact.getUrl()), artifact.getPath());
found = tryDownloadLibrary(library, artifact, url.toString(), outputPath);
}
// Try each repository if not found yet
if (!found) {
for (String baseUrl : mavenRepos) {

View File

@ -0,0 +1,113 @@
package com.skcraft.launcher.builder.loaders;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Iterables;
import com.google.common.io.Closer;
import com.skcraft.launcher.builder.BuilderUtils;
import com.skcraft.launcher.model.loader.MavenUrl;
import com.skcraft.launcher.model.loader.profiles.FabricInstallProfile;
import com.skcraft.launcher.model.minecraft.Library;
import com.skcraft.launcher.model.modpack.Manifest;
import com.skcraft.launcher.util.HttpRequest;
import lombok.extern.java.Log;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
@Log
public class FabricLoaderProcessor implements ILoaderProcessor {
@Override
public LoaderResult process(File loaderJar, Manifest manifest, ObjectMapper mapper, File baseDir) throws IOException {
JarFile jarFile = new JarFile(loaderJar);
LoaderResult result = new LoaderResult();
Closer closer = Closer.create();
try {
ZipEntry installerEntry = BuilderUtils.getZipEntry(jarFile, "fabric-installer.json");
if (installerEntry != null) {
InputStreamReader reader = new InputStreamReader(jarFile.getInputStream(installerEntry));
FabricInstallProfile profile = mapper.readValue(
BuilderUtils.readStringFromStream(closer.register(reader)), FabricInstallProfile.class);
// Check version
if (profile.getVersion() != 1) {
log.warning(String.format("Fabric installer metadata version is %d - we expect version 1.",
profile.getVersion()));
}
// Add libraries (TODO: Add server-only libraries to somewhere)
Iterable<Library> libraries = Iterables.concat(profile.getLibraries().getClient(),
profile.getLibraries().getCommon());
for (Library library : libraries) {
result.getLoaderLibraries().add(library);
log.info("Adding loader library " + library.getName());
}
// Add actual loader jar into library path
if (profile.getLoader() != null) {
result.getLoaderLibraries().add(profile.getLoader());
log.info(String.format("Adding Fabric Loader '%s'", profile.getLoader().getName()));
} else {
log.warning("Fabric loader metadata is missing a `loader` section, making up a fake library");
Library loader = new Library();
loader.setName("faked:loader:" + FilenameUtils.getBaseName(loaderJar.getName()));
Library.Downloads downloads = new Library.Downloads();
downloads.setArtifact(new Library.Artifact());
downloads.getArtifact().setPath(loaderJar.getName());
downloads.getArtifact().setUrl("");
loader.setDownloads(downloads);
result.getLoaderLibraries().add(loader);
// Little bit of a hack here, pretending the filesystem is a maven
result.getJarMavens().add(new URL("file:" + loaderJar.getParentFile().getAbsolutePath() + "/"));
}
// Set main class
String mainClass = profile.getMainClass().getClient();
if (mainClass != null) {
manifest.getVersionManifest().setMainClass(mainClass);
log.info("Using main class " + mainClass);
}
// Add intermediary library
log.info("Downloading fabric metadata...");
URL url = HttpRequest.url("https://meta.fabricmc.net/v2/versions/intermediary/"
+ manifest.getVersionManifest().getId());
List<MavenUrl> versions = HttpRequest.get(url)
.execute()
.expectResponseCode(200)
.returnContent()
.asJson(new TypeReference<List<MavenUrl>>() {});
if (versions != null && versions.size() > 0) {
MavenUrl intermediaryLib = versions.get(0);
if (intermediaryLib.getUrl() == null) {
// FIXME temporary hack since maven URL is missing, hopefully can go away soon
// waiting on PR FabricMC/fabric-meta#9
intermediaryLib.setUrl("https://maven.fabricmc.net/");
}
result.getLoaderLibraries().add(intermediaryLib.toLibrary());
log.info("Added intermediary " + intermediaryLib.getName());
}
}
} catch (InterruptedException e) {
log.warning("HTTP request to fabric metadata API was interrupted, this will probably not work!");
} finally {
closer.close();
jarFile.close();
}
return result;
}
}

View File

@ -51,7 +51,7 @@ public class ModernForgeLoaderProcessor implements ILoaderProcessor {
loaderName = version.getId();
}
// Copy tweak class arguments
// Copy game arguments
List<GameArgument> gameArguments = info.getArguments().getGameArguments();
if (gameArguments != null) {
version.getArguments().getGameArguments().addAll(gameArguments);

View File

@ -0,0 +1,10 @@
package com.skcraft.launcher.model.loader;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class ExtendedSidedData<T> extends SidedData<T> {
private T common;
}

View File

@ -14,7 +14,7 @@ import java.util.Map;
@NoArgsConstructor
public class LoaderManifest {
private List<Library> libraries;
private Map<String, SidedData> sidedData;
private Map<String, SidedData<String>> sidedData;
private List<DownloadableFile> downloadableFiles;
public Library findLibrary(String name) {

View File

@ -35,7 +35,7 @@ public class LoaderSubResolver {
char end = arg.charAt(bound);
if (start == '{' && end == '}') {
SidedData sidedData = loader.getSidedData().get(arg.substring(1, bound));
SidedData<String> sidedData = loader.getSidedData().get(arg.substring(1, bound));
if (sidedData != null) {
arg = sidedData.resolveFor(side);
}

View File

@ -0,0 +1,24 @@
package com.skcraft.launcher.model.loader;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.skcraft.launcher.model.minecraft.Library;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class MavenUrl {
@JsonProperty("maven")
private String name;
private String url;
private String version;
private boolean stable;
public Library toLibrary() {
Library library = new Library();
library.setName(name);
library.setUrl(url);
return library;
}
}

View File

@ -10,11 +10,11 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor(staticName = "create")
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class SidedData {
private String client;
private String server;
public class SidedData<T> {
private T client;
private T server;
public String resolveFor(Side side) {
public T resolveFor(Side side) {
switch (side) {
case CLIENT: return client;
case SERVER: return server;
@ -22,7 +22,7 @@ public class SidedData {
}
}
public static SidedData of(String singleValue) {
return new SidedData(singleValue, singleValue);
public static <T> SidedData<T> of(T singleValue) {
return new SidedData<T>(singleValue, singleValue);
}
}

View File

@ -0,0 +1,18 @@
package com.skcraft.launcher.model.loader.profiles;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.skcraft.launcher.model.loader.ExtendedSidedData;
import com.skcraft.launcher.model.loader.SidedData;
import com.skcraft.launcher.model.minecraft.Library;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FabricInstallProfile {
private int version;
private Library loader;
private ExtendedSidedData<List<Library>> libraries;
private SidedData<String> mainClass;
}

View File

@ -23,7 +23,7 @@ import java.util.Map;
public class ModernForgeInstallProfile {
private List<Library> libraries;
private List<InstallProcessor> processors;
private Map<String, SidedData> data;
private Map<String, SidedData<String>> data;
public List<ProcessorEntry> toProcessorEntries(final String loaderName) {
return Lists.transform(getProcessors(), new Function<InstallProcessor, ProcessorEntry>() {

View File

@ -55,9 +55,6 @@ public class VersionManifest {
}
setArguments(result);
// TODO: Possibly do some cheaty side-effects here to add parameters missing from early game versions.
// Either that or use a proper version adapter.
}
@Data

View File

@ -2,5 +2,6 @@
"https://libraries.minecraft.net/",
"https://repo1.maven.org/maven2/",
"https://files.minecraftforge.net/maven/",
"https://maven.fabricmc.net/",
"http://maven.apache.org/"
]