Split Minecraft and Forge jars (#34)

Signed-off-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
shedaniel
2021-07-14 18:21:03 +08:00
parent a82cafd382
commit 458acc482d
14 changed files with 315 additions and 98 deletions

View File

@@ -100,6 +100,10 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
configs.getByName(Constants.Configurations.MAPPINGS_FINAL)
);
if (extension.isForge()) {
processorConfig.extendsFrom(configs.getByName(Constants.Configurations.FORGE_NAMED));
}
// Add Mixin and mixin extensions (fabric-mixin-compile-extensions pulls mixin itself too)
project.getDependencies().add(processorConfig.getName(),
Constants.Dependencies.MIXIN_COMPILE_EXTENSIONS + Constants.Dependencies.Versions.MIXIN_COMPILE_EXTENSIONS);

View File

@@ -95,10 +95,17 @@ public final class CompileConfiguration {
forgeUniversalConfig.setTransitive(false);
Configuration forgeDependencies = project.getConfigurations().maybeCreate(Constants.Configurations.FORGE_DEPENDENCIES);
forgeDependencies.setTransitive(false);
Configuration forgeNamed = project.getConfigurations().maybeCreate(Constants.Configurations.FORGE_NAMED);
forgeNamed.setTransitive(false);
Configuration mcpConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MCP_CONFIG);
mcpConfig.setTransitive(false);
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
}
if (project.getExtensions().getByType(LoomGradleExtension.class).supportsInclude()) {

View File

@@ -69,6 +69,11 @@ public class MavenConfiguration {
});
});
project.getRepositories().maven(repo -> {
repo.setName("Architectury");
repo.setUrl("https://maven.architectury.dev/");
});
project.getRepositories().mavenCentral();
}
}

View File

@@ -166,6 +166,10 @@ public class ModProcessor {
remapper.readClassPathAsync(mc);
remapper.readClassPathAsync(mcDeps);
if (extension.isForge()) {
remapper.readClassPathAsync(mappedProvider.getForgeSrgJar().toPath());
}
final Map<ModDependencyInfo, InputTag> tagMap = new HashMap<>();
final Map<ModDependencyInfo, OutputConsumerPath> outputConsumerMap = new HashMap<>();
final Map<ModDependencyInfo, byte[]> accessWidenerMap = new HashMap<>();

View File

@@ -177,6 +177,10 @@ public class LaunchProvider extends DependencyProvider {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getIntermediaryJar());
if (getExtension().isForge()) {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getForgeIntermediaryJar());
}
String str = remapClasspath.stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));

View File

@@ -48,6 +48,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -58,11 +59,13 @@ import java.util.stream.Stream;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import com.google.gson.JsonParser;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import net.minecraftforge.binarypatcher.ConsoleTool;
@@ -86,7 +89,6 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvid
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.JarUtil;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.function.FsPathConsumer;
@@ -96,7 +98,7 @@ import net.fabricmc.mapping.tree.TinyTree;
public class MinecraftPatchedProvider extends DependencyProvider {
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
private static final String CURRENT_LOOM_PATCH_VERSION = "3";
private static final String CURRENT_LOOM_PATCH_VERSION = "4";
private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService";
// Step 1: Remap Minecraft to SRG (global)
@@ -109,8 +111,9 @@ public class MinecraftPatchedProvider extends DependencyProvider {
private File minecraftMergedPatchedSrgJar;
// Step 4: Access Transform (global or project)
private File minecraftMergedPatchedSrgAtJar;
// Step 5: Remap Patched AT to Official (global or project)
// Step 5: Remap Patched AT & Forge to Official (global or project)
private File minecraftMergedPatchedJar;
private File forgeMergedJar;
private File projectAtHash;
private Set<File> projectAts = new HashSet<>();
@@ -177,6 +180,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
minecraftClientPatchedSrgJar = new File(globalDir, "client-srg-patched.jar");
minecraftServerPatchedSrgJar = new File(globalDir, "server-srg-patched.jar");
minecraftMergedPatchedSrgJar = new File(globalDir, "merged-srg-patched.jar");
forgeMergedJar = new File(globalDir, "forge-official.jar");
minecraftMergedPatchedSrgAtJar = new File(projectDir, "merged-srg-at-patched.jar");
minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar");
@@ -214,6 +218,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
minecraftClientPatchedSrgJar,
minecraftServerPatchedSrgJar,
minecraftMergedPatchedSrgJar,
forgeMergedJar,
};
}
@@ -251,7 +256,6 @@ public class MinecraftPatchedProvider extends DependencyProvider {
if (!minecraftClientPatchedSrgJar.exists() || !minecraftServerPatchedSrgJar.exists()) {
this.dirty = true;
patchJars(getProject().getLogger());
injectForgeClasses(getProject().getLogger());
}
}
@@ -265,14 +269,37 @@ public class MinecraftPatchedProvider extends DependencyProvider {
accessTransformForge(getProject().getLogger());
}
if (!forgeMergedJar.exists()) {
this.dirty = true;
}
Path input = minecraftMergedPatchedSrgAtJar.toPath();
if (dirty) {
remapPatchedJar(getProject().getLogger());
remapPatchedJar(input, getProject().getLogger());
}
this.filesDirty = dirty;
this.dirty = false;
}
private TinyRemapper buildRemapper(Path input) throws IOException {
Path[] libraries = MinecraftMappedProvider.getRemapClasspath(getProject());
TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
TinyRemapper remapper = TinyRemapper.newRemapper()
.logger(getProject().getLogger()::lifecycle)
.logUnknownInvokeDynamic(false)
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.fixPackageAccess(true)
.build();
remapper.readClassPath(libraries);
remapper.prepareClasses();
return remapper;
}
private void writeAtHash() throws IOException {
try (FileOutputStream out = new FileOutputStream(projectAtHash)) {
out.write(getProjectAtsHash());
@@ -349,12 +376,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath() + " in " + stopwatch);
}
private void injectForgeClasses(Logger logger) throws IOException {
logger.lifecycle(":injecting forge classes into minecraft");
ThreadingUtils.run(Environment.values(), environment -> {
copyAll(getExtension().getForgeUniversalProvider().getForge(), environment.patchedSrgJar.apply(this));
copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), environment.patchedSrgJar.apply(this));
});
private File getForgeJar() {
return getExtension().getForgeUniversalProvider().getForge();
}
private File getForgeUserdevJar() {
return getExtension().getForgeUserdevProvider().getUserdevJar();
}
private boolean isPatchedJarUpToDate(File jar) {
@@ -380,6 +407,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void accessTransformForge(Logger logger) throws Exception {
List<File> toDelete = new ArrayList<>();
String atDependency = Constants.Dependencies.ACCESS_TRANSFORMERS + Constants.Dependencies.Versions.ACCESS_TRANSFORMERS;
FileCollection classpath = DependencyDownloader.download(getProject(), atDependency);
@@ -388,17 +416,27 @@ public class MinecraftPatchedProvider extends DependencyProvider {
File input = minecraftMergedPatchedSrgJar;
File target = minecraftMergedPatchedSrgAtJar;
Files.deleteIfExists(target.toPath());
File at = File.createTempFile("at-conf", ".cfg");
at.deleteOnExit();
JarUtil.extractFile(input, "META-INF/accesstransformer.cfg", at);
List<String> args = new ArrayList<>();
args.add("--inJar");
args.add(input.getAbsolutePath());
args.add("--outJar");
args.add(target.getAbsolutePath());
args.add("--atFile");
args.add(at.getAbsolutePath());
for (File jar : ImmutableList.of(getForgeJar(), getForgeUserdevJar(), minecraftMergedPatchedSrgJar)) {
try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(jar, false)) {
Path atPath = fs.get().getPath("META-INF/accesstransformer.cfg");
if (Files.exists(atPath)) {
File tmpFile = File.createTempFile("at-conf", ".cfg");
tmpFile.delete();
toDelete.add(tmpFile);
Files.copy(atPath, tmpFile.toPath());
args.add("--atFile");
args.add(tmpFile.getAbsolutePath());
}
}
}
if (usesProjectCache()) {
for (File projectAt : projectAts) {
@@ -420,6 +458,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);
}
}).rethrowFailure().assertNormalExitValue();
for (File file : toDelete) {
file.delete();
}
}
public enum Environment {
@@ -444,35 +486,35 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
}
private void remapPatchedJar(Logger logger) throws Exception {
Path[] libraries = MinecraftMappedProvider.getRemapClasspath(getProject());
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)");
TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
private void remapPatchedJar(Path input, Logger logger) throws Exception {
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, srg -> official)");
Path mcOutput = minecraftMergedPatchedJar.toPath();
Path forgeOutput = forgeMergedJar.toPath();
Path forgeJar = getForgeJar().toPath();
Path forgeUserdevJar = getForgeUserdevJar().toPath();
Files.deleteIfExists(mcOutput);
Files.deleteIfExists(forgeOutput);
TinyRemapper remapper = buildRemapper(input);
Path input = minecraftMergedPatchedSrgAtJar.toPath();
Path output = minecraftMergedPatchedJar.toPath();
Files.deleteIfExists(output);
TinyRemapper remapper = TinyRemapper.newRemapper()
.logger(getProject().getLogger()::lifecycle)
.logUnknownInvokeDynamic(false)
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.fixPackageAccess(true)
.build();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build();
OutputConsumerPath outputConsumerForge = new OutputConsumerPath.Builder(forgeOutput).build()) {
outputConsumer.addNonClassFiles(input);
remapper.readClassPath(libraries);
remapper.readInputs(input);
remapper.apply(outputConsumer);
InputTag mcTag = remapper.createInputTag();
InputTag forgeTag = remapper.createInputTag();
List<CompletableFuture<?>> futures = new ArrayList<>();
futures.add(remapper.readInputsAsync(mcTag, input));
futures.add(remapper.readInputsAsync(forgeTag, forgeJar, forgeUserdevJar));
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
remapper.apply(outputConsumer, mcTag);
remapper.apply(outputConsumerForge, forgeTag);
} finally {
remapper.finish();
}
applyLoomPatchVersion(mcOutput);
copyNonClassFiles(forgeJar.toFile(), forgeMergedJar);
copyUserdevFiles(forgeUserdevJar.toFile(), forgeMergedJar);
}
private void patchJars(Logger logger) throws IOException {
@@ -574,7 +616,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
private void copyNonClassFiles(File source, File target) throws IOException {
Predicate<Path> filter = file -> {
String s = file.toString();
return !s.endsWith(".class") && !s.equalsIgnoreCase("/META-INF/MANIFEST.MF");
return !s.endsWith(".class");
};
walkFileSystems(source, target, filter, this::copyReplacing);
@@ -595,7 +637,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
// If there are multiple name mapping services with the same "understanding" pair
// (source -> target namespace pair), modlauncher throws a fit and will crash.
// To use our YarnNamingService instead of MCPNamingService, we have to remove this file.
Predicate<Path> filter = file -> !file.toString().equals(NAME_MAPPING_SERVICE_PATH);
Predicate<Path> filter = file -> !file.toString().endsWith(".class") && !file.toString().equals(NAME_MAPPING_SERVICE_PATH);
walkFileSystems(source, target, filter, fs -> Collections.singleton(fs.getPath("inject")), (sourceFs, targetFs, sourcePath, targetPath) -> {
Path parent = targetPath.getParent();
@@ -606,16 +648,20 @@ public class MinecraftPatchedProvider extends DependencyProvider {
Files.copy(sourcePath, targetPath);
});
}
public void applyLoomPatchVersion(Path target) throws IOException {
try (FileSystemUtil.FileSystemDelegate delegate = FileSystemUtil.getJarFileSystem(target, false)) {
Path manifestPath = delegate.get().getPath("META-INF/MANIFEST.MF");
Preconditions.checkArgument(Files.exists(manifestPath), "META-INF/MANIFEST.MF does not exist in patched srg jar!");
Manifest manifest = new Manifest();
try (InputStream stream = Files.newInputStream(manifestPath)) {
manifest.read(stream);
manifest.getMainAttributes().putValue(LOOM_PATCH_VERSION_KEY, CURRENT_LOOM_PATCH_VERSION);
if (Files.exists(manifestPath)) {
try (InputStream stream = Files.newInputStream(manifestPath)) {
manifest.read(stream);
manifest.getMainAttributes().putValue(LOOM_PATCH_VERSION_KEY, CURRENT_LOOM_PATCH_VERSION);
}
}
try (OutputStream stream = Files.newOutputStream(manifestPath)) {
@@ -628,6 +674,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
return minecraftMergedPatchedJar;
}
public File getForgeMergedJar() {
return forgeMergedJar;
}
public boolean usesProjectCache() {
return !projectAts.isEmpty();
}

View File

@@ -39,6 +39,7 @@ import java.util.function.Consumer;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.NonClassCopyMode;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
@@ -69,9 +70,13 @@ public class MinecraftMappedProvider extends DependencyProvider {
.build();
private File inputJar;
private File inputForgeJar;
private File minecraftMappedJar;
private File minecraftIntermediaryJar;
private File minecraftSrgJar;
private File forgeMappedJar;
private File forgeIntermediaryJar;
private File forgeSrgJar;
private MinecraftProvider minecraftProvider;
@@ -90,8 +95,17 @@ public class MinecraftMappedProvider extends DependencyProvider {
}
boolean isForgeAtDirty = getExtension().isForge() && getExtension().getMappingsProvider().patchedProvider.isAtDirty();
boolean needToRemap = false;
if (!minecraftMappedJar.exists() || !getIntermediaryJar().exists() || (getExtension().isForge() && !getSrgJar().exists()) || isRefreshDeps() || isForgeAtDirty) {
needToRemap = true;
}
if (getExtension().isForge() && (!getForgeMappedJar().exists() || !getForgeIntermediaryJar().exists() || !getForgeSrgJar().exists() || isRefreshDeps() || isForgeAtDirty)) {
needToRemap = true;
}
if (needToRemap) {
if (minecraftMappedJar.exists()) {
minecraftMappedJar.delete();
}
@@ -106,8 +120,20 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftSrgJar.delete();
}
if (getExtension().isForge()) {
if (getForgeMappedJar().exists()) {
getForgeMappedJar().delete();
}
getForgeMappedJar().getParentFile().mkdirs();
getForgeIntermediaryJar().delete();
getForgeSrgJar().delete();
}
try {
mapMinecraftJar();
TinyRemapper[] remapperArray = new TinyRemapper[] {null};
mapMinecraftJar(remapperArray);
remapperArray[0].finish();
} catch (Throwable t) {
// Cleanup some some things that may be in a bad state now
DownloadUtil.delete(minecraftMappedJar);
@@ -115,7 +141,10 @@ public class MinecraftMappedProvider extends DependencyProvider {
getExtension().getMinecraftProvider().deleteFiles();
if (getExtension().isForge()) {
minecraftSrgJar.delete();
DownloadUtil.delete(minecraftSrgJar);
DownloadUtil.delete(forgeMappedJar);
DownloadUtil.delete(forgeSrgJar);
DownloadUtil.delete(forgeIntermediaryJar);
}
getExtension().getMappingsProvider().cleanFiles();
@@ -129,36 +158,31 @@ public class MinecraftMappedProvider extends DependencyProvider {
addDependencies(dependency, postPopulationScheduler);
getProject().afterEvaluate(project -> {
if (getExtension().isForge() && !OperatingSystem.isCIBuild()) {
try {
ForgeSourcesRemapper.addBaseForgeSources(project);
} catch (IOException e) {
e.printStackTrace();
if (getExtension().isForge()) {
getProject().getDependencies().add(Constants.Configurations.FORGE_NAMED,
getProject().getDependencies().module("net.minecraftforge-loom:forge:" + getJarVersionString("mapped")));
getProject().afterEvaluate(project -> {
if (!OperatingSystem.isCIBuild()) {
try {
ForgeSourcesRemapper.addBaseForgeSources(project);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
});
}
}
private void mapMinecraftJar() throws Exception {
String fromM = "official";
MappingsProvider mappingsProvider = getExtension().getMappingsProvider();
Path input = inputJar.toPath();
Path outputMapped = minecraftMappedJar.toPath();
Path outputIntermediary = minecraftIntermediaryJar.toPath();
Path outputSrg = minecraftSrgJar == null ? null : minecraftSrgJar.toPath();
private TinyRemapper buildRemapper() throws IOException {
Path[] libraries = getRemapClasspath(getProject());
TinyRemapper remapper = getTinyRemapper();
remapper.readClassPath(libraries);
remapper.prepareClasses();
return remapper;
}
Path tmpAssets = Files.createTempFile("tmpAssets", null);
Files.deleteIfExists(tmpAssets);
tmpAssets.toFile().deleteOnExit();
private byte[][] inputBytes(Path input) throws IOException {
List<byte[]> inputByteList = new ArrayList<>();
try (FileSystemUtil.FileSystemDelegate inputFs = FileSystemUtil.getJarFileSystem(input, false)) {
@@ -181,38 +205,102 @@ public class MinecraftMappedProvider extends DependencyProvider {
taskCompleter.complete();
}
try (OutputConsumerPath tmpAssetsPath = new OutputConsumerPath.Builder(tmpAssets).assumeArchive(true).build()) {
if (getExtension().isForge()) {
tmpAssetsPath.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, null);
} else {
tmpAssetsPath.addNonClassFiles(input);
return inputByteList.toArray(new byte[0][0]);
}
private void assetsOut(Path input, @Nullable Path assetsOut) throws IOException {
if (assetsOut != null) {
try (OutputConsumerPath tmpAssetsPath = new OutputConsumerPath.Builder(assetsOut).assumeArchive(true).build()) {
if (getExtension().isForge()) {
tmpAssetsPath.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, null);
} else {
tmpAssetsPath.addNonClassFiles(input);
}
}
}
}
byte[][] inputBytes = inputByteList.toArray(new byte[0][0]);
private void mapMinecraftJar(TinyRemapper[] remapperArray) throws Exception {
Path input = inputJar.toPath();
Path inputForge = inputForgeJar == null ? null : inputForgeJar.toPath();
Path outputMapped = minecraftMappedJar.toPath();
Path outputIntermediary = minecraftIntermediaryJar.toPath();
Path outputSrg = minecraftSrgJar == null ? null : minecraftSrgJar.toPath();
Path forgeOutputMapped = forgeMappedJar == null ? null : forgeMappedJar.toPath();
Path forgeOutputIntermediary = forgeIntermediaryJar == null ? null : forgeIntermediaryJar.toPath();
Path forgeOutputSrg = forgeSrgJar == null ? null : forgeSrgJar.toPath();
Path vanillaAssets = Files.createTempFile("assets", null);
Files.deleteIfExists(vanillaAssets);
vanillaAssets.toFile().deleteOnExit();
Path forgeAssets = Files.createTempFile("assets", null);
Files.deleteIfExists(forgeAssets);
forgeAssets.toFile().deleteOnExit();
Info vanilla = new Info(vanillaAssets, input, outputMapped, outputIntermediary, outputSrg);
Info forge = getExtension().isForge() ? new Info(forgeAssets, inputForge, forgeOutputMapped, forgeOutputIntermediary, forgeOutputSrg) : null;
TinyRemapper remapper = remapperArray[0] = buildRemapper();
assetsOut(input, vanillaAssets);
if ( getExtension().isForge()) {
assetsOut(inputForge, forgeAssets);
}
remap(remapper, vanilla, forge, "official");
}
public static class Info {
Path assets;
Path input;
Path outputMapped;
Path outputIntermediary;
Path outputSrg;
public Info(Path assets, Path input, Path outputMapped, Path outputIntermediary, Path outputSrg) {
this.assets = assets;
this.input = input;
this.outputMapped = outputMapped;
this.outputIntermediary = outputIntermediary;
this.outputSrg = outputSrg;
}
}
public void remap(TinyRemapper remapper, Info vanilla, @Nullable Info forge, String fromM) throws IOException {
for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) {
Path output = "named".equals(toM) ? outputMapped : "srg".equals(toM) ? outputSrg : outputIntermediary;
Path output = "named".equals(toM) ? vanilla.outputMapped : "srg".equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary;
Path outputForge = forge == null ? null : "named".equals(toM) ? forge.outputMapped : "srg".equals(toM) ? forge.outputSrg : forge.outputIntermediary;
InputTag vanillaTag = remapper.createInputTag();
InputTag forgeTag = remapper.createInputTag();
Stopwatch stopwatch = Stopwatch.createStarted();
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
remapper.readInputs(inputBytes);
remapper.replaceMappings(getMappings(input, fromM, toM));
OutputRemappingHandler.remap(remapper, tmpAssets, output);
remapper.readInputs(vanillaTag, vanilla.input);
if (forge != null) {
remapper.readInputs(forgeTag, forge.input);
}
remapper.replaceMappings(getMappings(vanilla.input, fromM, toM));
OutputRemappingHandler.remap(remapper, vanilla.assets, output, null, vanillaTag);
if (forge != null) {
OutputRemappingHandler.remap(remapper, forge.assets, outputForge, null, forgeTag);
}
getProject().getLogger().lifecycle(":remapped minecraft (TinyRemapper, " + fromM + " -> " + toM + ") in " + stopwatch);
remapper.removeInput();
if (getExtension().isForge() && !"srg".equals(toM)) {
getProject().getLogger().info(":running forge finalising tasks");
getProject().getLogger().info(":running minecraft finalising tasks");
TinyTree yarnWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
AtRemapper.remap(getProject().getLogger(), output, yarnWithSrg);
CoreModClassRemapper.remapJar(output, yarnWithSrg, getProject().getLogger());
}
}
remapper.finish();
}
public TinyRemapper getTinyRemapper() throws IOException {
@@ -268,6 +356,12 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftSrgJar = !getExtension().isForge() ? null : new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("srg") + ".jar");
minecraftMappedJar = new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("mapped") + ".jar");
inputJar = getExtension().isForge() ? mappingsProvider.patchedProvider.getMergedJar() : minecraftProvider.getMergedJar();
if (getExtension().isForge()) {
inputForgeJar = mappingsProvider.patchedProvider.getForgeMergedJar();
forgeIntermediaryJar = new File(getExtension().getUserCache(), "forge-" + getJarVersionString("intermediary") + ".jar");
forgeSrgJar = new File(getExtension().getUserCache(), "forge-" + getJarVersionString("srg") + ".jar");
forgeMappedJar = new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "forge-" + getJarVersionString("mapped") + ".jar");
}
}
protected File getJarDirectory(File parentDirectory, String type) {
@@ -290,6 +384,18 @@ public class MinecraftMappedProvider extends DependencyProvider {
return minecraftMappedJar;
}
public File getForgeIntermediaryJar() {
return forgeIntermediaryJar;
}
public File getForgeSrgJar() {
return forgeSrgJar;
}
public File getForgeMappedJar() {
return forgeMappedJar;
}
public File getUnpickedJar() {
return new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("unpicked") + ".jar");
}

View File

@@ -59,7 +59,7 @@ import net.fabricmc.lorenztiny.TinyMappingsReader;
public class ForgeSourcesRemapper {
public static void addBaseForgeSources(Project project) throws IOException {
Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar").toPath();
Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar", true).toPath();
if (!Files.exists(sourcesJar)) {
addForgeSources(project, sourcesJar);
@@ -185,6 +185,7 @@ public class ForgeSourcesRemapper {
// Distinct and add the srg jar at the top, so it gets prioritized
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getSrgJar().toPath());
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
List<Path> newClassPath = mercury.getClassPath().stream()
.distinct()
.filter(Files::isRegularFile)

View File

@@ -110,9 +110,13 @@ public class GenerateSourcesTask extends AbstractLoomTask {
}
public static File getMappedJarFileWithSuffix(Project project, String suffix) {
return getMappedJarFileWithSuffix(project, suffix, false);
}
public static File getMappedJarFileWithSuffix(Project project, String suffix, boolean forgeJar) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider();
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
File mappedJar = forgeJar ? mappingsProvider.mappedProvider.getForgeMappedJar() : mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {

View File

@@ -101,7 +101,7 @@ public class MigrateMappingsTask extends AbstractLoomTask {
try {
TinyTree currentMappings = mappingsProvider.getMappings();
TinyTree targetMappings = getMappings(mappings);
migrateMappings(project, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings);
migrateMappings(project, extension, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings);
project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath());
} catch (IOException e) {
throw new IllegalArgumentException("Error while loading mappings", e);
@@ -158,8 +158,8 @@ public class MigrateMappingsTask extends AbstractLoomTask {
}
}
private static void migrateMappings(Project project, MinecraftMappedProvider minecraftMappedProvider,
Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings
private static void migrateMappings(Project project, LoomGradleExtension extension, MinecraftMappedProvider minecraftMappedProvider,
Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings
) throws IOException {
project.getLogger().info(":joining mappings");
@@ -183,6 +183,13 @@ public class MigrateMappingsTask extends AbstractLoomTask {
mercury.getClassPath().add(minecraftMappedProvider.getMappedJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getIntermediaryJar().toPath());
if (extension.isForge()) {
mercury.getClassPath().add(minecraftMappedProvider.getSrgJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeMappedJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeIntermediaryJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeSrgJar().toPath());
}
mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
try {

View File

@@ -86,6 +86,7 @@ public class Constants {
public static final String FORGE_INSTALLER = "forgeInstaller";
public static final String FORGE_UNIVERSAL = "forgeUniversal";
public static final String FORGE_DEPENDENCIES = "forgeDependencies";
public static final String FORGE_NAMED = "forgeNamed";
@Deprecated // Not to be used in gradle 7+
public static final String COMPILE = "compile";
public static final String MAPPING_CONSTANTS = "mappingsConstants";

View File

@@ -209,6 +209,9 @@ public class SourceRemapper {
if (extension.isForge()) {
m.getClassPath().add(extension.getMinecraftMappedProvider().getSrgJar().toPath());
m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeMappedJar().toPath());
m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeIntermediaryJar().toPath());
m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
}
Set<File> files = project.getConfigurations()

View File

@@ -34,9 +34,11 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
public class ThreadingUtils {
@@ -136,25 +138,34 @@ public class ThreadingUtils {
}
public static class TaskCompleter implements Function<Throwable, Void> {
private final ReentrantLock lock = new ReentrantLock();
private boolean canAdd = true;
Stopwatch stopwatch = Stopwatch.createUnstarted();
List<CompletableFuture<?>> tasks = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<UnsafeConsumer<Stopwatch>> completionListener = new ArrayList<>();
public TaskCompleter add(UnsafeRunnable job) {
if (!stopwatch.isRunning()) {
stopwatch.start();
}
Preconditions.checkArgument(canAdd);
lock.lock();
tasks.add(CompletableFuture.runAsync(() -> {
try {
job.run();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
try {
if (!stopwatch.isRunning()) {
stopwatch.start();
}
}, service).exceptionally(this));
return this;
tasks.add(CompletableFuture.runAsync(() -> {
try {
job.run();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}, service).exceptionally(this));
return this;
} finally {
lock.unlock();
}
}
public TaskCompleter onComplete(UnsafeConsumer<Stopwatch> consumer) {
@@ -163,6 +174,8 @@ public class ThreadingUtils {
}
public void complete() {
canAdd = false;
try {
CompletableFuture.allOf(tasks.toArray(new CompletableFuture[0])).exceptionally(this).get();
service.shutdownNow();

View File

@@ -35,8 +35,10 @@ import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
@@ -83,8 +85,14 @@ public class SpecialSourceExecutor {
spec.setClasspath(specialSourceCp);
spec.workingDir(workingDir.toFile());
spec.setMain("net.md_5.specialsource.SpecialSource");
spec.setStandardOutput(System.out);
spec.setErrorOutput(System.out);
// if running with INFO or DEBUG logging
if (project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
spec.setStandardOutput(System.out);
} else {
spec.setStandardOutput(NullOutputStream.NULL_OUTPUT_STREAM);
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);
}
}).rethrowFailure().assertNormalExitValue();
Files.deleteIfExists(stripped);