From aafd69b4729e8ef538a59f33a8d7ef3877eab2c2 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:55:37 +0200 Subject: [PATCH] Read loader access transformers from userdev config (#254) Fixes #253. MinecraftPatchedProvider now respects the userdev config's AT declaration. It also only tries to find the ATs from the userdev jar as a slight optimisation. --- .../loom/forge/UserdevConfig.java | 44 ++++++++++++++- .../AccessTransformerJarProcessor.java | 1 + .../forge/MinecraftPatchedProvider.java | 56 +++++++++++++------ 3 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/main/java/dev/architectury/loom/forge/UserdevConfig.java b/src/main/java/dev/architectury/loom/forge/UserdevConfig.java index a22aecb55..c96b62da3 100644 --- a/src/main/java/dev/architectury/loom/forge/UserdevConfig.java +++ b/src/main/java/dev/architectury/loom/forge/UserdevConfig.java @@ -1,13 +1,17 @@ package dev.architectury.loom.forge; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Function; +import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.fabricmc.loom.configuration.providers.forge.ForgeRunTemplate; +import net.fabricmc.loom.util.IOFunction; public record UserdevConfig( String mcp, @@ -20,7 +24,8 @@ public record UserdevConfig( BinaryPatcherConfig binpatcher, List libraries, Map runs, - List sass + List sass, + AccessTransformerLocation ats ) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.fieldOf("mcp").forGetter(UserdevConfig::mcp), @@ -33,7 +38,8 @@ public record UserdevConfig( BinaryPatcherConfig.CODEC.fieldOf("binpatcher").forGetter(UserdevConfig::binpatcher), Codec.STRING.listOf().fieldOf("libraries").forGetter(UserdevConfig::libraries), ForgeRunTemplate.MAP_CODEC.fieldOf("runs").forGetter(UserdevConfig::runs), - Codec.STRING.listOf().optionalFieldOf("sass", List.of()).forGetter(UserdevConfig::sass) + Codec.STRING.listOf().optionalFieldOf("sass", List.of()).forGetter(UserdevConfig::sass), + AccessTransformerLocation.CODEC.fieldOf("ats").forGetter(UserdevConfig::ats) ).apply(instance, UserdevConfig::new)); public record BinaryPatcherConfig(String dependency, List args) { @@ -42,4 +48,38 @@ public record BinaryPatcherConfig(String dependency, List args) { Codec.STRING.listOf().fieldOf("args").forGetter(BinaryPatcherConfig::args) ).apply(instance, BinaryPatcherConfig::new)); } + + public sealed interface AccessTransformerLocation { + Codec CODEC = Codec.either(Codec.STRING, Codec.STRING.listOf()).xmap( + either -> either.map(Directory::new, FileList::new), + location -> location.visit(Either::left, Either::right) + ); + + T visit(Function ifDirectory, Function, T> ifFileList); + T visitIo(IOFunction ifDirectory, IOFunction, T> ifFileList) throws IOException; + + record Directory(String path) implements AccessTransformerLocation { + @Override + public T visit(Function ifDirectory, Function, T> ifFileList) { + return ifDirectory.apply(path); + } + + @Override + public T visitIo(IOFunction ifDirectory, IOFunction, T> ifFileList) throws IOException { + return ifDirectory.apply(path); + } + } + + record FileList(List paths) implements AccessTransformerLocation { + @Override + public T visit(Function ifDirectory, Function, T> ifFileList) { + return ifFileList.apply(paths); + } + + @Override + public T visitIo(IOFunction ifDirectory, IOFunction, T> ifFileList) throws IOException { + return ifFileList.apply(paths); + } + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java index 223210340..c7f81bce9 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java @@ -97,6 +97,7 @@ public AccessTransformerJarProcessor(String name, Project project, Iterable atSources = List.of( - extension.getForgeUniversalProvider().getForge().toPath(), - extension.getForgeUserdevProvider().getUserdevJar().toPath(), - ((ForgeMinecraftProvider) extension.getMinecraftProvider()) - .getPatchedProvider() - .getMinecraftPatchedIntermediateJar() - ); - + Path userdevJar = extension.getForgeUserdevProvider().getUserdevJar().toPath(); Files.deleteIfExists(target); try (var tempFiles = new TempFiles()) { AccessTransformerJarProcessor.executeAt(project, input, target, args -> { - for (Path jar : atSources) { - byte[] atBytes = ZipUtils.unpackNullable(jar, Constants.Forge.ACCESS_TRANSFORMER_PATH); - - if (atBytes != null) { - Path tmpFile = tempFiles.file("at-conf", ".cfg"); - Files.write(tmpFile, atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - args.add("--atFile"); - args.add(tmpFile.toAbsolutePath().toString()); - } + for (String atFile : extractAccessTransformers(userdevJar, extension.getForgeUserdevProvider().getConfig().ats(), tempFiles)) { + args.add("--atFile"); + args.add(atFile); } }); } @@ -397,6 +385,38 @@ public static void accessTransform(Project project, Path input, Path target) thr project.getLogger().lifecycle(":access transformed minecraft in " + stopwatch.stop()); } + private static List extractAccessTransformers(Path jar, UserdevConfig.AccessTransformerLocation location, TempFiles tempFiles) throws IOException { + final List extracted = new ArrayList<>(); + + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar)) { + for (Path atFile : getAccessTransformerPaths(fs, location)) { + byte[] atBytes; + + try { + atBytes = Files.readAllBytes(atFile); + } catch (NoSuchFileException e) { + continue; + } + + Path tmpFile = tempFiles.file("at-conf", ".cfg"); + Files.write(tmpFile, atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + extracted.add(tmpFile.toAbsolutePath().toString()); + } + } + + return extracted; + } + + private static List getAccessTransformerPaths(FileSystemUtil.Delegate fs, UserdevConfig.AccessTransformerLocation location) throws IOException { + return location.visitIo(directory -> { + Path dirPath = fs.getPath(directory); + + try (Stream paths = Files.list(dirPath)) { + return paths.toList(); + } + }, paths -> paths.stream().map(fs::getPath).toList()); + } + private void remapPatchedJar(ServiceFactory serviceFactory) throws Exception { logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)"); Path mcInput = minecraftPatchedIntermediateAtJar;