mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-28 04:07:01 -05:00
Split Minecraft and Forge jars (#34)
Signed-off-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -69,6 +69,11 @@ public class MavenConfiguration {
|
||||
});
|
||||
});
|
||||
|
||||
project.getRepositories().maven(repo -> {
|
||||
repo.setName("Architectury");
|
||||
repo.setUrl("https://maven.architectury.dev/");
|
||||
});
|
||||
|
||||
project.getRepositories().mavenCentral();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user