Skip to content

Commit f9cfe89

Browse files
committed
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.
1 parent b1061bb commit f9cfe89

File tree

3 files changed

+81
-20
lines changed

3 files changed

+81
-20
lines changed

src/main/java/dev/architectury/loom/forge/UserdevConfig.java

+42-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package dev.architectury.loom.forge;
22

3+
import java.io.IOException;
34
import java.util.List;
45
import java.util.Map;
56
import java.util.Optional;
7+
import java.util.function.Function;
68

9+
import com.mojang.datafixers.util.Either;
710
import com.mojang.serialization.Codec;
811
import com.mojang.serialization.codecs.RecordCodecBuilder;
912

1013
import net.fabricmc.loom.configuration.providers.forge.ForgeRunTemplate;
14+
import net.fabricmc.loom.util.IOFunction;
1115

1216
public record UserdevConfig(
1317
String mcp,
@@ -20,7 +24,8 @@ public record UserdevConfig(
2024
BinaryPatcherConfig binpatcher,
2125
List<String> libraries,
2226
Map<String, ForgeRunTemplate> runs,
23-
List<String> sass
27+
List<String> sass,
28+
AccessTransformerLocation ats
2429
) {
2530
public static final Codec<UserdevConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
2631
Codec.STRING.fieldOf("mcp").forGetter(UserdevConfig::mcp),
@@ -33,7 +38,8 @@ public record UserdevConfig(
3338
BinaryPatcherConfig.CODEC.fieldOf("binpatcher").forGetter(UserdevConfig::binpatcher),
3439
Codec.STRING.listOf().fieldOf("libraries").forGetter(UserdevConfig::libraries),
3540
ForgeRunTemplate.MAP_CODEC.fieldOf("runs").forGetter(UserdevConfig::runs),
36-
Codec.STRING.listOf().optionalFieldOf("sass", List.of()).forGetter(UserdevConfig::sass)
41+
Codec.STRING.listOf().optionalFieldOf("sass", List.of()).forGetter(UserdevConfig::sass),
42+
AccessTransformerLocation.CODEC.fieldOf("ats").forGetter(UserdevConfig::ats)
3743
).apply(instance, UserdevConfig::new));
3844

3945
public record BinaryPatcherConfig(String dependency, List<String> args) {
@@ -42,4 +48,38 @@ public record BinaryPatcherConfig(String dependency, List<String> args) {
4248
Codec.STRING.listOf().fieldOf("args").forGetter(BinaryPatcherConfig::args)
4349
).apply(instance, BinaryPatcherConfig::new));
4450
}
51+
52+
public sealed interface AccessTransformerLocation {
53+
Codec<AccessTransformerLocation> CODEC = Codec.either(Codec.STRING, Codec.STRING.listOf()).xmap(
54+
either -> either.map(Directory::new, FileList::new),
55+
location -> location.visit(Either::left, Either::right)
56+
);
57+
58+
<T> T visit(Function<String, T> ifDirectory, Function<List<String>, T> ifFileList);
59+
<T> T visitIo(IOFunction<String, T> ifDirectory, IOFunction<List<String>, T> ifFileList) throws IOException;
60+
61+
record Directory(String path) implements AccessTransformerLocation {
62+
@Override
63+
public <T> T visit(Function<String, T> ifDirectory, Function<List<String>, T> ifFileList) {
64+
return ifDirectory.apply(path);
65+
}
66+
67+
@Override
68+
public <T> T visitIo(IOFunction<String, T> ifDirectory, IOFunction<List<String>, T> ifFileList) throws IOException {
69+
return ifDirectory.apply(path);
70+
}
71+
}
72+
73+
record FileList(List<String> paths) implements AccessTransformerLocation {
74+
@Override
75+
public <T> T visit(Function<String, T> ifDirectory, Function<List<String>, T> ifFileList) {
76+
return ifFileList.apply(paths);
77+
}
78+
79+
@Override
80+
public <T> T visitIo(IOFunction<String, T> ifDirectory, IOFunction<List<String>, T> ifFileList) throws IOException {
81+
return ifFileList.apply(paths);
82+
}
83+
}
84+
}
4585
}

src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public AccessTransformerJarProcessor(String name, Project project, Iterable<File
9797
final byte[] bytes;
9898

9999
try {
100+
// TODO: Shouldn't we check for the mods.toml AT list on Neo?
100101
bytes = localMod.getSource().read(Constants.Forge.ACCESS_TRANSFORMER_PATH);
101102
} catch (FileNotFoundException | NoSuchFileException e) {
102103
continue;

src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java

+38-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of fabric-loom, licensed under the MIT License (MIT).
33
*
4-
* Copyright (c) 2020-2023 FabricMC
4+
* Copyright (c) 2020-2024 FabricMC
55
*
66
* Permission is hereby granted, free of charge, to any person obtaining a copy
77
* of this software and associated documentation files (the "Software"), to deal
@@ -32,6 +32,7 @@
3232
import java.io.UncheckedIOException;
3333
import java.nio.file.FileSystem;
3434
import java.nio.file.Files;
35+
import java.nio.file.NoSuchFileException;
3536
import java.nio.file.Path;
3637
import java.nio.file.StandardCopyOption;
3738
import java.nio.file.StandardOpenOption;
@@ -373,34 +374,53 @@ public static void accessTransform(Project project, Path input, Path target) thr
373374
project.getLogger().lifecycle(":access transforming minecraft");
374375

375376
LoomGradleExtension extension = LoomGradleExtension.get(project);
376-
List<Path> atSources = List.of(
377-
extension.getForgeUniversalProvider().getForge().toPath(),
378-
extension.getForgeUserdevProvider().getUserdevJar().toPath(),
379-
((ForgeMinecraftProvider) extension.getMinecraftProvider())
380-
.getPatchedProvider()
381-
.getMinecraftPatchedIntermediateJar()
382-
);
383-
377+
Path userdevJar = extension.getForgeUserdevProvider().getUserdevJar().toPath();
384378
Files.deleteIfExists(target);
385379

386380
try (var tempFiles = new TempFiles()) {
387381
AccessTransformerJarProcessor.executeAt(project, input, target, args -> {
388-
for (Path jar : atSources) {
389-
byte[] atBytes = ZipUtils.unpackNullable(jar, Constants.Forge.ACCESS_TRANSFORMER_PATH);
390-
391-
if (atBytes != null) {
392-
Path tmpFile = tempFiles.file("at-conf", ".cfg");
393-
Files.write(tmpFile, atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
394-
args.add("--atFile");
395-
args.add(tmpFile.toAbsolutePath().toString());
396-
}
382+
for (String atFile : extractAccessTransformers(userdevJar, extension.getForgeUserdevProvider().getConfig().ats(), tempFiles)) {
383+
args.add("--atFile");
384+
args.add(atFile);
397385
}
398386
});
399387
}
400388

401389
project.getLogger().lifecycle(":access transformed minecraft in " + stopwatch.stop());
402390
}
403391

392+
private static List<String> extractAccessTransformers(Path jar, UserdevConfig.AccessTransformerLocation location, TempFiles tempFiles) throws IOException {
393+
final List<String> extracted = new ArrayList<>();
394+
395+
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar)) {
396+
for (Path atFile : getAccessTransformerPaths(fs, location)) {
397+
byte[] atBytes;
398+
399+
try {
400+
atBytes = Files.readAllBytes(atFile);
401+
} catch (NoSuchFileException e) {
402+
continue;
403+
}
404+
405+
Path tmpFile = tempFiles.file("at-conf", ".cfg");
406+
Files.write(tmpFile, atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
407+
extracted.add(tmpFile.toAbsolutePath().toString());
408+
}
409+
}
410+
411+
return extracted;
412+
}
413+
414+
private static List<Path> getAccessTransformerPaths(FileSystemUtil.Delegate fs, UserdevConfig.AccessTransformerLocation location) throws IOException {
415+
return location.visitIo(directory -> {
416+
Path dirPath = fs.getPath(directory);
417+
418+
try (Stream<Path> paths = Files.list(dirPath)) {
419+
return paths.toList();
420+
}
421+
}, paths -> paths.stream().map(fs::getPath).toList());
422+
}
423+
404424
private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception {
405425
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)");
406426
Path mcInput = minecraftPatchedIntermediateAtJar;

0 commit comments

Comments
 (0)