1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2024-11-27 12:46:22 +01:00

Add support for Forge 1.17 processors

This commit is contained in:
Henry Le Grys 2021-09-02 06:56:57 +01:00
parent eda5ad2a90
commit 7c783189dd
7 changed files with 118 additions and 8 deletions

View File

@ -18,10 +18,7 @@ import com.skcraft.launcher.model.modpack.Manifest;
import com.skcraft.launcher.util.FileUtils;
import lombok.extern.java.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.*;
import java.net.URL;
import java.util.List;
import java.util.jar.JarFile;
@ -61,6 +58,12 @@ public class ModernForgeLoaderProcessor implements ILoaderProcessor {
version.getArguments().getGameArguments().addAll(gameArguments);
}
// Copy JVM arguments
List<GameArgument> jvmArguments = info.getArguments().getJvmArguments();
if (jvmArguments != null) {
version.getArguments().getJvmArguments().addAll(jvmArguments);
}
// Add libraries
List<Library> libraries = info.getLibraries();
if (libraries != null) {
@ -101,11 +104,13 @@ public class ModernForgeLoaderProcessor implements ILoaderProcessor {
// Extract the data files
List<DownloadableFile> extraFiles = Lists.newArrayList();
File objectsDir = new File(baseDir, manifest.getObjectsLocation());
ZipEntry clientBinpatch = BuilderUtils.getZipEntry(jarFile, "data/client.lzma");
if (clientBinpatch != null) {
DownloadableFile entry = FileUtils.saveStreamToObjectsDir(
closer.register(jarFile.getInputStream(clientBinpatch)),
new File(baseDir, manifest.getObjectsLocation()));
objectsDir);
entry.setName("client.lzma");
entry.setSide(Side.CLIENT);
@ -117,7 +122,7 @@ public class ModernForgeLoaderProcessor implements ILoaderProcessor {
if (serverBinpatch != null) {
DownloadableFile entry = FileUtils.saveStreamToObjectsDir(
closer.register(jarFile.getInputStream(serverBinpatch)),
new File(baseDir, manifest.getObjectsLocation()));
objectsDir);
entry.setName("server.lzma");
entry.setSide(Side.SERVER);
@ -125,6 +130,20 @@ public class ModernForgeLoaderProcessor implements ILoaderProcessor {
profile.getData().get("BINPATCH").setServer("&" + entry.getName() + "&");
}
// Forge install profile spec version 1 and above.
if (profile.getSpec() >= 1) {
// Add the installer itself to the extra files.
// This is for a server-only task like above, but hey.
DownloadableFile entry = FileUtils.saveStreamToObjectsDir(
closer.register(new FileInputStream(loaderJar)), objectsDir);
entry.setName(loaderJar.getName());
entry.setSide(Side.SERVER);
extraFiles.add(entry);
profile.getData().put("INSTALLER", SidedData.of("&" + entry.getName() + "&"));
}
// Add extra sided data
profile.getData().put("SIDE", SidedData.create("client", "server"));

View File

@ -42,11 +42,16 @@ public class ProcessorTask implements InstallTask {
@Override
public void execute(Launcher launcher) throws Exception {
VersionManifest versionManifest = manifest.getVersionManifest();
loaderManifest.getSidedData().put("MINECRAFT_JAR", SidedData.of(launcher.getJarPath(versionManifest).getAbsolutePath()));
LoaderSubResolver resolver = new LoaderSubResolver(manifest, loaderManifest,
Environment.getInstance(), Side.CLIENT, launcher.getBaseDir(), localFiles);
Map<String, SidedData<String>> sidedData = loaderManifest.getSidedData();
sidedData.put("ROOT", SidedData.of(launcher.getInstallerDir().getAbsolutePath()));
sidedData.put("MINECRAFT_JAR", SidedData.of(launcher.getJarPath(versionManifest).getAbsolutePath()));
sidedData.put("LIBRARY_DIR", SidedData.of(resolver.getPathOf(manifest.getLibrariesLocation())));
sidedData.put("MINECRAFT_VERSION", SidedData.of(versionManifest.getId()));
message = "Resolving parameters";
List<String> programArgs = processor.resolveArgs(resolver);
Map<String, String> outputs = processor.resolveOutputs(resolver);
@ -83,6 +88,7 @@ public class ProcessorTask implements InstallTask {
message = "Executing";
log.info(String.format("Running processor '%s' with %d args", processor.getJar(), programArgs.size()));
log.info("Arguments: [" + String.join(", ", programArgs) + "]");
ClassLoader parent;
try {
@ -94,13 +100,19 @@ public class ProcessorTask implements InstallTask {
parent = null;
}
ClassLoader prev = Thread.currentThread().getContextClassLoader();
ClassLoader cl = new URLClassLoader(classpath.toArray(new URL[0]), parent);
try {
Class<?> mainClazz = Class.forName(mainClass, true, cl);
Method main = mainClazz.getDeclaredMethod("main", String[].class);
// engage spicy mode
Thread.currentThread().setContextClassLoader(cl);
main.invoke(null, (Object) programArgs.toArray(new String[0]));
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
Thread.currentThread().setContextClassLoader(prev);
}
message = "Verifying";
@ -118,6 +130,7 @@ public class ProcessorTask implements InstallTask {
}
if (!FileUtils.getShaHash(artifact).equals(output.getValue())) {
log.warning("Invalid hash, expected " + output.getValue());
throw new RuntimeException(String.format("Artifact '%s' has invalid hash!", output.getKey()));
}

View File

@ -429,6 +429,10 @@ public class Runner implements Callable<Process>, ProgressObservable {
map.put("classpath", builder.buildClassPath());
map.put("natives_directory", extractDir.getAbsolutePath());
// Forge additions
map.put("library_directory", launcher.getLibrariesDir().getAbsolutePath());
map.put("classpath_separator", System.getProperty("path.separator"));
return map;
}

View File

@ -2,6 +2,7 @@ package com.skcraft.launcher.model.loader;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.google.common.collect.Lists;
import com.skcraft.launcher.model.minecraft.Side;
import lombok.Data;
import java.util.Collections;
@ -16,6 +17,7 @@ public class InstallProcessor {
private List<String> classpath;
private List<String> args;
private Map<String, String> outputs;
private List<String> sides;
public List<String> resolveArgs(LoaderSubResolver resolver) {
return Lists.transform(getArgs(), resolver);
@ -32,4 +34,19 @@ public class InstallProcessor {
return result;
}
public boolean shouldRunOn(Side side) {
if (sides == null) {
return true;
}
switch (side) {
case CLIENT:
return sides.contains("client");
case SERVER:
return sides.contains("server");
}
return false;
}
}

View File

@ -33,6 +33,8 @@ public class LoaderSubResolver implements Function<String, String> {
public String apply(String arg) {
if (arg == null) return null;
arg = replaceTokens(arg);
while (true) {
char start = arg.charAt(0);
int bound = arg.length() - 1;
@ -66,4 +68,55 @@ public class LoaderSubResolver implements Function<String, String> {
}
}
}
private String replaceTokens(String arg) {
StringBuilder buf = new StringBuilder();
int length = arg.length();
for (int i = 0; i < length; i++) {
char c = arg.charAt(i);
if (c == '\\') {
buf.append(arg.charAt(i + 1));
i++;
} else if (c == '{' || c == '\'') {
StringBuilder keyBuf = new StringBuilder();
for (int j = i + 1; j <= length; j++) {
if (j == length) {
throw new IllegalArgumentException("Illegal pattern: unclosed " + c);
}
char d = arg.charAt(j);
if (d == '\\') {
keyBuf.append(arg.charAt(j + 1));
j++;
} else if (c == '{' && d == '}') {
String key = keyBuf.toString();
SidedData<String> sidedData = loader.getSidedData().get(key);
if (sidedData != null) {
buf.append(sidedData.resolveFor(side));
} else {
throw new IllegalArgumentException("Missing key: " + key);
}
i = j;
break;
} else if (c == '\'' && d == '\'') {
buf.append(keyBuf.toString());
i = j;
break;
} else {
keyBuf.append(d);
}
}
} else {
buf.append(c);
}
}
return buf.toString();
}
}

View File

@ -1,6 +1,7 @@
package com.skcraft.launcher.model.loader;
import com.skcraft.launcher.install.*;
import com.skcraft.launcher.model.minecraft.Side;
import com.skcraft.launcher.model.modpack.ManifestEntry;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -19,6 +20,8 @@ public class ProcessorEntry extends ManifestEntry {
public void install(Installer installer, InstallLog log, UpdateCache cache, InstallExtras extras) throws Exception {
LocalLoader loader = extras.getLoader(loaderName);
installer.queueLate(new ProcessorTask(processor, loader.getManifest(), getManifest(), loader.getLocalFiles()));
if (processor.shouldRunOn(Side.CLIENT)) {
installer.queueLate(new ProcessorTask(processor, loader.getManifest(), getManifest(), loader.getLocalFiles()));
}
}
}

View File

@ -21,6 +21,7 @@ import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ModernForgeInstallProfile {
private int spec;
private List<Library> libraries;
private List<InstallProcessor> processors;
private Map<String, SidedData<String>> data;