mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-02 21:47:42 -05:00
MappingsProvider: Add mapping file augmented with SRG when Forge support is enabled
This commit is contained in:
@@ -47,6 +47,7 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DependencyProvider;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.stitch.Command;
|
||||
@@ -72,6 +73,7 @@ public class MappingsProvider extends DependencyProvider {
|
||||
public File tinyMappings;
|
||||
public File tinyMappingsJar;
|
||||
public File mappingsMixinExport;
|
||||
private Path tinyMappingsWithSrg;
|
||||
|
||||
public MappingsProvider(Project project) {
|
||||
super(project);
|
||||
@@ -85,6 +87,14 @@ public class MappingsProvider extends DependencyProvider {
|
||||
return MappingsCache.INSTANCE.get(tinyMappings.toPath());
|
||||
}
|
||||
|
||||
public TinyTree getMappingsWithSrg() throws IOException {
|
||||
if (getExtension().isForge()) {
|
||||
return MappingsCache.INSTANCE.get(tinyMappingsWithSrg);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Not running with Forge support.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class);
|
||||
@@ -129,6 +139,7 @@ public class MappingsProvider extends DependencyProvider {
|
||||
|
||||
tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile();
|
||||
tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar"));
|
||||
tinyMappingsWithSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-srg.tiny");
|
||||
|
||||
if (!tinyMappings.exists() || isRefreshDeps()) {
|
||||
storeMappings(getProject(), minecraftProvider, mappingsJar.toPath());
|
||||
@@ -138,6 +149,10 @@ public class MappingsProvider extends DependencyProvider {
|
||||
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
|
||||
}
|
||||
|
||||
if (getExtension().isForge() && (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps())) {
|
||||
SrgMerger.mergeSrg(getExtension().getMcpConfigProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg);
|
||||
}
|
||||
|
||||
addDependency(tinyMappingsJar, Constants.MAPPINGS_FINAL);
|
||||
|
||||
JarProcessorManager processorManager = new JarProcessorManager(getProject());
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package net.fabricmc.loom.util.function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Stream-like utilities for working with collections.
|
||||
*
|
||||
* @author Juuz
|
||||
*/
|
||||
public final class CollectionUtil {
|
||||
/**
|
||||
* Finds the first element matching the predicate.
|
||||
*
|
||||
* @param collection the collection to be searched
|
||||
* @param filter the predicate to be matched
|
||||
* @param <E> the element type
|
||||
* @return the first matching element, or empty if none match
|
||||
*/
|
||||
public static <E> Optional<E> find(Iterable<? extends E> collection, Predicate<? super E> filter) {
|
||||
for (E e : collection) {
|
||||
if (filter.test(e)) {
|
||||
return Optional.of(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the collection with a function.
|
||||
*
|
||||
* @param collection the source collection
|
||||
* @param transform the transformation function
|
||||
* @param <A> the source type
|
||||
* @param <B> the target type
|
||||
* @return a mutable list with the transformed entries
|
||||
*/
|
||||
public static <A, B> List<B> map(Iterable<? extends A> collection, Function<? super A, ? extends B> transform) {
|
||||
ArrayList<B> result = new ArrayList<>();
|
||||
|
||||
for (A a : collection) {
|
||||
result.add(transform.apply(a));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.fabricmc.loom.util.srg;
|
||||
|
||||
/**
|
||||
* An exception that occurs when processing obfuscation mappings.
|
||||
*
|
||||
* @author Juuz
|
||||
*/
|
||||
public class MappingException extends RuntimeException {
|
||||
public MappingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
137
src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java
Normal file
137
src/main/java/net/fabricmc/loom/util/srg/SrgMerger.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package net.fabricmc.loom.util.srg;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader;
|
||||
import org.cadixdev.lorenz.model.ClassMapping;
|
||||
import org.cadixdev.lorenz.model.FieldMapping;
|
||||
import org.cadixdev.lorenz.model.InnerClassMapping;
|
||||
import org.cadixdev.lorenz.model.MethodMapping;
|
||||
import org.cadixdev.lorenz.model.TopLevelClassMapping;
|
||||
|
||||
import net.fabricmc.loom.util.function.CollectionUtil;
|
||||
import net.fabricmc.mapping.tree.ClassDef;
|
||||
import net.fabricmc.mapping.tree.FieldDef;
|
||||
import net.fabricmc.mapping.tree.MethodDef;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyClass;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyField;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyHeader;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyMethod;
|
||||
import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer;
|
||||
|
||||
/**
|
||||
* Utilities for merging SRG mappings.
|
||||
*
|
||||
* @author Juuz
|
||||
*/
|
||||
public final class SrgMerger {
|
||||
/**
|
||||
* Merges SRG mappings with a tiny mappings tree through the obf names.
|
||||
*
|
||||
* @param srg the SRG file in .tsrg format
|
||||
* @param tiny the tiny file
|
||||
* @param out the output file, will be in tiny v2
|
||||
* @throws IOException if an IO error occurs while reading or writing the mappings
|
||||
* @throws MappingException if the input tiny tree's default namespace is not 'official'
|
||||
* or if an element mentioned in the SRG file does not have tiny mappings
|
||||
*/
|
||||
public static void mergeSrg(Path srg, Path tiny, Path out) throws IOException, MappingException {
|
||||
MappingSet arr;
|
||||
TinyTree foss;
|
||||
|
||||
try (TSrgReader reader = new TSrgReader(Files.newBufferedReader(srg))) {
|
||||
arr = reader.read();
|
||||
}
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(tiny)) {
|
||||
foss = TinyMappingFactory.loadWithDetection(reader);
|
||||
}
|
||||
|
||||
List<String> namespaces = new ArrayList<>(foss.getMetadata().getNamespaces());
|
||||
namespaces.add(1, "srg");
|
||||
|
||||
if (!"official".equals(namespaces.get(0))) {
|
||||
throw new MappingException("Mapping file " + tiny + " does not have the 'official' namespace as the default!");
|
||||
}
|
||||
|
||||
TinyHeader header = new TinyHeader(namespaces, 2, 0, Collections.emptyMap());
|
||||
|
||||
List<TinyClass> classes = new ArrayList<>();
|
||||
|
||||
for (TopLevelClassMapping klass : arr.getTopLevelClassMappings()) {
|
||||
classToTiny(foss, namespaces, klass, classes::add);
|
||||
}
|
||||
|
||||
TinyFile file = new TinyFile(header, classes);
|
||||
TinyV2Writer.write(file, out);
|
||||
}
|
||||
|
||||
private static void classToTiny(TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer) {
|
||||
String obf = klass.getFullObfuscatedName();
|
||||
String srg = klass.getFullDeobfuscatedName();
|
||||
ClassDef classDef = foss.getDefaultNamespaceClassMap().get(obf);
|
||||
|
||||
if (classDef == null) {
|
||||
throw new MappingException("Missing class: " + obf + " (srg: " + srg + ")");
|
||||
}
|
||||
|
||||
List<String> classNames = CollectionUtil.map(
|
||||
namespaces,
|
||||
namespace -> "srg".equals(namespace) ? srg : classDef.getName(namespace)
|
||||
);
|
||||
|
||||
List<TinyMethod> methods = new ArrayList<>();
|
||||
List<TinyField> fields = new ArrayList<>();
|
||||
|
||||
for (MethodMapping method : klass.getMethodMappings()) {
|
||||
MethodDef def = CollectionUtil.find(
|
||||
classDef.getMethods(),
|
||||
m -> m.getName("official").equals(method.getObfuscatedName()) && m.getDescriptor("official").equals(method.getObfuscatedDescriptor())
|
||||
).orElseThrow(() -> new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")"));
|
||||
|
||||
List<String> methodNames = CollectionUtil.map(
|
||||
namespaces,
|
||||
namespace -> "srg".equals(namespace) ? method.getDeobfuscatedName() : def.getName(namespace)
|
||||
);
|
||||
|
||||
methods.add(new TinyMethod(
|
||||
def.getDescriptor("official"), methodNames,
|
||||
/* parameters */ Collections.emptyList(),
|
||||
/* locals */ Collections.emptyList(),
|
||||
/* comments */ Collections.emptyList()
|
||||
));
|
||||
}
|
||||
|
||||
for (FieldMapping field : klass.getFieldMappings()) {
|
||||
FieldDef def = CollectionUtil.find(
|
||||
classDef.getFields(),
|
||||
f -> f.getName("official").equals(field.getObfuscatedName())
|
||||
).orElseThrow(() -> new MappingException("Missing field: " + field.getFullObfuscatedName() + " (srg: " + field.getFullDeobfuscatedName() + ")"));
|
||||
|
||||
List<String> fieldNames = CollectionUtil.map(
|
||||
namespaces,
|
||||
namespace -> "srg".equals(namespace) ? field.getDeobfuscatedName() : field.getObfuscatedName()
|
||||
);
|
||||
|
||||
fields.add(new TinyField(def.getDescriptor("official"), fieldNames, Collections.emptyList()));
|
||||
}
|
||||
|
||||
TinyClass tinyClass = new TinyClass(classNames, methods, fields, Collections.emptyList());
|
||||
classConsumer.accept(tinyClass);
|
||||
|
||||
for (InnerClassMapping innerKlass : klass.getInnerClassMappings()) {
|
||||
classToTiny(foss, namespaces, innerKlass, classConsumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user