mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-02 05:27:43 -05:00
Merge remote-tracking branch 'FabricMC/dev/0.10' into dev/0.10.0
# Conflicts: # build.gradle # src/main/java/net/fabricmc/loom/LoomGradleExtension.java # src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java # src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java # src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java # src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilderImpl.java # src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java # src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java # src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java # src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java # src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java # src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java # src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java # src/main/java/net/fabricmc/loom/task/RemapJarTask.java # src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java # src/main/java/net/fabricmc/loom/util/SourceRemapper.java # src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java # src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
package net.fabricmc.loom;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -38,6 +39,7 @@ import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.configuration.InstallerData;
|
||||
import net.fabricmc.loom.configuration.LoomDependencyManager;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
|
||||
@@ -111,6 +113,10 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
@Override
|
||||
MixinExtension getMixin();
|
||||
|
||||
List<AccessWidenerFile> getTransitiveAccessWideners();
|
||||
|
||||
void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles);
|
||||
|
||||
// ===================
|
||||
// Architectury Loom
|
||||
// ===================
|
||||
|
||||
@@ -43,7 +43,6 @@ import net.fabricmc.loom.configuration.CompileConfiguration;
|
||||
import net.fabricmc.loom.configuration.FabricApiExtension;
|
||||
import net.fabricmc.loom.configuration.MavenPublication;
|
||||
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
|
||||
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
|
||||
import net.fabricmc.loom.extension.LoomFiles;
|
||||
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
|
||||
@@ -78,7 +77,6 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
|
||||
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies() || "true".equals(System.getProperty("loom.refresh"));
|
||||
|
||||
if (refreshDeps) {
|
||||
MappingsCache.INSTANCE.invalidate();
|
||||
project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower.");
|
||||
}
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ import org.gradle.api.publish.maven.MavenPublication;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfig;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.util.DeprecationHelper;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
|
||||
@@ -213,6 +213,13 @@ public interface LoomGradleExtensionAPI {
|
||||
*/
|
||||
String getModVersion();
|
||||
|
||||
/**
|
||||
* When true loom will apply transitive access wideners from compile dependencies.
|
||||
*
|
||||
* @return the property controlling the transitive access wideners
|
||||
*/
|
||||
Property<Boolean> getEnableTransitiveAccessWideners();
|
||||
|
||||
// ===================
|
||||
// Architectury Loom
|
||||
// ===================
|
||||
|
||||
@@ -22,16 +22,22 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
package net.fabricmc.loom.api.mappings.layered;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
|
||||
@ApiStatus.Experimental /* Very Experimental and not cleanly separated from the impl atm */
|
||||
public interface MappingContext {
|
||||
File mavenFile(String mavenNotation);
|
||||
Path resolveDependency(Dependency dependency);
|
||||
|
||||
Path resolveMavenDependency(String mavenNotation);
|
||||
|
||||
MappingsProvider mappingsProvider();
|
||||
|
||||
@@ -44,7 +50,7 @@ public interface MappingContext {
|
||||
/**
|
||||
* Creates a temporary working dir to be used to store working files.
|
||||
*/
|
||||
File workingDirectory(String name);
|
||||
Path workingDirectory(String name);
|
||||
|
||||
Logger getLogger();
|
||||
}
|
||||
@@ -22,21 +22,28 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
package net.fabricmc.loom.api.mappings.layered;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public interface MappingLayer {
|
||||
void visit(MappingVisitor mappingVisitor) throws IOException;
|
||||
|
||||
default MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.NAMED;
|
||||
default MappingsNamespace getSourceNamespace() {
|
||||
return MappingsNamespace.NAMED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of layer classes that this mapping layer depends on. If such a layer is not present an Exception will be thrown when trying to resolve the layer.
|
||||
* @return A list of MappingLayer classes to depend on.
|
||||
*/
|
||||
default List<Class<? extends MappingLayer>> dependsOn() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.api.mappings.layered;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The standard namespaces used by loom.
|
||||
*/
|
||||
public enum MappingsNamespace {
|
||||
/**
|
||||
* Official mappings are the names that are used in the vanilla Minecraft game jars, these are usually obfuscated.
|
||||
*/
|
||||
OFFICIAL,
|
||||
|
||||
/**
|
||||
* Intermediary mappings have been generated to provide a stable set of names across minecraft versions.
|
||||
*
|
||||
* <p>Intermediary is used in a production runtime (outside a dev env) allowing mods to run across multiple versions of the game. Mods are remapped from "named" at build time.
|
||||
*
|
||||
* @see <a href="https://github.com/FabricMC/intermediary/">github.com/FabricMC/intermediary/</a>
|
||||
*/
|
||||
INTERMEDIARY,
|
||||
|
||||
/**
|
||||
* Named mappings are the developer friendly names used to develop mods against.
|
||||
*/
|
||||
NAMED;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.api.mappings.layered.spec;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.utils.DependencyFileSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.utils.LocalFileSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.utils.MavenFileSpec;
|
||||
|
||||
/**
|
||||
* FileSpec should be used in MappingsSpec's that take an input file. The input file can either be a local file or a gradle dep.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public interface FileSpec {
|
||||
static FileSpec create(Object o) {
|
||||
Objects.requireNonNull(o, "Object cannot be null");
|
||||
|
||||
if (o instanceof String s) {
|
||||
return createFromMavenDependency(s);
|
||||
} else if (o instanceof Dependency d) {
|
||||
return createFromDependency(d);
|
||||
} else if (o instanceof File f) {
|
||||
return createFromFile(f);
|
||||
} else if (o instanceof RegularFileProperty rfp) {
|
||||
return createFromFile(rfp);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Cannot create FileSpec from object of type:" + o.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
static FileSpec createFromMavenDependency(String dependencyNotation) {
|
||||
return new MavenFileSpec(dependencyNotation);
|
||||
}
|
||||
|
||||
static FileSpec createFromDependency(Dependency dependency) {
|
||||
return new DependencyFileSpec(dependency);
|
||||
}
|
||||
|
||||
static FileSpec createFromFile(File file) {
|
||||
return new LocalFileSpec(file);
|
||||
}
|
||||
|
||||
// Note resolved instantly, this is not lazy
|
||||
static FileSpec createFromFile(RegularFileProperty regularFileProperty) {
|
||||
return createFromFile(regularFileProperty.getAsFile().get());
|
||||
}
|
||||
|
||||
Path get(MappingContext context);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.api.mappings.layered.spec;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Used to configure a layered mapping spec.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public interface LayeredMappingSpecBuilder {
|
||||
/**
|
||||
* Add a MappingsSpec layer.
|
||||
*/
|
||||
LayeredMappingSpecBuilder addLayer(MappingsSpec<?> mappingSpec);
|
||||
|
||||
/**
|
||||
* Add a layer that uses the official mappings provided by Mojang.
|
||||
*/
|
||||
LayeredMappingSpecBuilder officialMojangMappings();
|
||||
|
||||
default LayeredMappingSpecBuilder parchment(Object object) {
|
||||
return parchment(object, parchmentMappingsSpecBuilder -> parchmentMappingsSpecBuilder.setRemovePrefix(true));
|
||||
}
|
||||
|
||||
LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action);
|
||||
}
|
||||
@@ -22,8 +22,21 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
package net.fabricmc.loom.api.mappings.layered.spec;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
|
||||
/**
|
||||
* A MappingsSpec is an immutable set of data used to create the MappingLayer.
|
||||
*
|
||||
* <p>The hashCode is used to generate a hash of the full layered mapping spec, used to cache.
|
||||
*
|
||||
* <p>Commonly implemented as a record
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public interface MappingsSpec<L extends MappingLayer> {
|
||||
L createLayer(MappingContext context);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2021 FabricMC
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,16 +22,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
package net.fabricmc.loom.api.mappings.layered.spec;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public enum MappingNamespace {
|
||||
OFFICIAL,
|
||||
INTERMEDIARY,
|
||||
NAMED;
|
||||
|
||||
public String stringValue() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
@ApiStatus.Experimental
|
||||
public interface ParchmentMappingsSpecBuilder {
|
||||
/**
|
||||
* When enabled the "p" prefix will be stripped from parameter names.
|
||||
*/
|
||||
ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
public record AccessWidenerFile(
|
||||
String name,
|
||||
String modId,
|
||||
byte[] content
|
||||
) {
|
||||
/**
|
||||
* Reads the access-widener contained in a mod jar, or returns null if there is none.
|
||||
*/
|
||||
public static AccessWidenerFile fromModJar(Path modJarPath) {
|
||||
byte[] modJsonBytes = ZipUtil.unpackEntry(modJarPath.toFile(), "fabric.mod.json");
|
||||
|
||||
if (modJsonBytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject jsonObject = new Gson().fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class);
|
||||
|
||||
if (!jsonObject.has("accessWidener")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String awPath = jsonObject.get("accessWidener").getAsString();
|
||||
String modId = jsonObject.get("id").getAsString();
|
||||
|
||||
byte[] content = ZipUtil.unpackEntry(modJarPath.toFile(), awPath);
|
||||
|
||||
return new AccessWidenerFile(
|
||||
awPath,
|
||||
modId,
|
||||
content
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -24,46 +24,38 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.common.hash.Hashing;
|
||||
import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.AccessWidenerWriter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
private AccessWidener accessWidener = new AccessWidener();
|
||||
private AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener);
|
||||
// Filename used to store hash of input access widener in processed jar file
|
||||
private static final String HASH_FILENAME = "aw.sha256";
|
||||
// The mod's own access widener file
|
||||
private byte[] modAccessWidener;
|
||||
private final AccessWidener accessWidener = new AccessWidener();
|
||||
private final Project project;
|
||||
// This is a SHA256 hash across the mod's and all transitive AWs
|
||||
private byte[] inputHash;
|
||||
|
||||
public AccessWidenerJarProcessor(Project project) {
|
||||
@@ -77,121 +69,53 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project);
|
||||
File awPath = loomGradleExtension.getAccessWidenerPath().get().getAsFile();
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
Path awPath = extension.getAccessWidenerPath().get().getAsFile().toPath();
|
||||
|
||||
if (!awPath.exists()) {
|
||||
throw new RuntimeException("Could not find access widener file @ " + awPath.getAbsolutePath());
|
||||
}
|
||||
|
||||
inputHash = Checksum.sha256(awPath);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(awPath))) {
|
||||
accessWidenerReader.read(reader);
|
||||
// Read our own mod's access widener, used later for producing a version remapped to intermediary
|
||||
try {
|
||||
modAccessWidener = Files.readAllBytes(awPath);
|
||||
} catch (NoSuchFileException e) {
|
||||
throw new RuntimeException("Could not find access widener file @ " + awPath.toAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read project access widener file");
|
||||
throw new RuntimeException("Failed to read access widener: " + awPath);
|
||||
}
|
||||
|
||||
//Remap accessWidener if its not named, allows for AE's to be written in intermediary
|
||||
if (!accessWidener.getNamespace().equals("named")) {
|
||||
try {
|
||||
List<String> validNamespaces = loomGradleExtension.getMappingsProvider().getMappings().getMetadata().getNamespaces();
|
||||
AccessWidenerReader reader = new AccessWidenerReader(accessWidener);
|
||||
reader.read(modAccessWidener);
|
||||
|
||||
if (!validNamespaces.contains(accessWidener.getNamespace())) {
|
||||
throw new UnsupportedOperationException(String.format("Access Widener namespace '%s' is not a valid namespace, it must be one of: '%s'", accessWidener.getNamespace(), String.join(", ", validNamespaces)));
|
||||
}
|
||||
|
||||
TinyRemapper tinyRemapper = loomGradleExtension.getMinecraftMappedProvider().getTinyRemapper();
|
||||
tinyRemapper.replaceMappings(loomGradleExtension.getMinecraftMappedProvider().getMappings(null, "official", "named"));
|
||||
loomGradleExtension.getMinecraftMappedProvider();
|
||||
tinyRemapper.readClassPath(MinecraftMappedProvider.getRemapClasspath(project));
|
||||
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, tinyRemapper.getRemapper(), "named");
|
||||
accessWidener = remapper.remap();
|
||||
|
||||
tinyRemapper.finish();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to remap access widener", e);
|
||||
}
|
||||
}
|
||||
inputHash = Hashing.sha256().hashBytes(modAccessWidener).asBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(File file) {
|
||||
project.getLogger().lifecycle("Processing file: " + file.getName());
|
||||
ZipUtil.transformEntries(file, getTransformers(accessWidener.getTargets()));
|
||||
ZipUtil.addEntry(file, "aw.sha256", inputHash);
|
||||
AccessWidenerTransformer applier = new AccessWidenerTransformer(project.getLogger(), accessWidener);
|
||||
applier.apply(file);
|
||||
ZipUtil.addEntry(file, HASH_FILENAME, inputHash);
|
||||
}
|
||||
|
||||
private ZipEntryTransformerEntry[] getTransformers(Set<String> classes) {
|
||||
return classes.stream()
|
||||
.map(string -> new ZipEntryTransformerEntry(string.replaceAll("\\.", "/") + ".class", getTransformer(string)))
|
||||
.toArray(ZipEntryTransformerEntry[]::new);
|
||||
}
|
||||
/**
|
||||
* Get this mods access widener remapped to the intermediary namespace.
|
||||
*/
|
||||
public byte[] getRemappedAccessWidener(Remapper asmRemapper, String targetNamespace) throws IOException {
|
||||
int version = AccessWidenerReader.readVersion(modAccessWidener);
|
||||
|
||||
private ZipEntryTransformer getTransformer(String className) {
|
||||
return new ByteArrayZipEntryTransformer() {
|
||||
@Override
|
||||
protected byte[] transform(ZipEntry zipEntry, byte[] input) {
|
||||
ClassReader reader = new ClassReader(input);
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
ClassVisitor classVisitor = AccessWidenerVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener);
|
||||
AccessWidenerWriter writer = new AccessWidenerWriter(version);
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(
|
||||
writer,
|
||||
asmRemapper,
|
||||
MappingsNamespace.NAMED.toString(),
|
||||
targetNamespace
|
||||
);
|
||||
AccessWidenerReader reader = new AccessWidenerReader(remapper);
|
||||
reader.read(modAccessWidener);
|
||||
|
||||
project.getLogger().lifecycle("Applying access widener to " + className);
|
||||
|
||||
reader.accept(classVisitor, 0);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//Called when remapping the mod
|
||||
public void remapAccessWidener(Path modJarPath, Remapper asmRemapper) throws IOException {
|
||||
byte[] bytes = getRemappedAccessWidener(asmRemapper);
|
||||
|
||||
String path = getAccessWidenerPath(modJarPath);
|
||||
|
||||
if (path == null) {
|
||||
throw new RuntimeException("Failed to find accessWidener in fabric.mod.json");
|
||||
}
|
||||
|
||||
boolean replaced = ZipUtil.replaceEntry(modJarPath.toFile(), path, bytes);
|
||||
|
||||
if (!replaced) {
|
||||
project.getLogger().warn("Failed to replace access widener file at " + path);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getRemappedAccessWidener(Remapper asmRemapper) throws IOException {
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, asmRemapper, "intermediary");
|
||||
AccessWidener remapped = remapper.remap();
|
||||
AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped);
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
accessWidenerWriter.write(writer);
|
||||
return writer.toString().getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
public String getAccessWidenerPath(Path modJarPath) {
|
||||
byte[] modJsonBytes = ZipUtil.unpackEntry(modJarPath.toFile(), "fabric.mod.json");
|
||||
|
||||
if (modJsonBytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject jsonObject = new Gson().fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class);
|
||||
|
||||
if (!jsonObject.has("accessWidener")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return jsonObject.get("accessWidener").getAsString();
|
||||
return writer.write();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalid(File file) {
|
||||
byte[] hash = ZipUtil.unpackEntry(file, "aw.sha256");
|
||||
byte[] hash = ZipUtil.unpackEntry(file, HASH_FILENAME);
|
||||
|
||||
if (hash == null) {
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerClassVisitor;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
final class AccessWidenerTransformer {
|
||||
private final Logger logger;
|
||||
private final AccessWidener accessWidener;
|
||||
|
||||
AccessWidenerTransformer(Logger logger, AccessWidener accessWidener) {
|
||||
this.logger = logger;
|
||||
this.accessWidener = accessWidener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the rules from an access-widener to the given jar or zip file.
|
||||
*/
|
||||
void apply(File jarFile) {
|
||||
logger.lifecycle("Processing file: " + jarFile.getName());
|
||||
ZipUtil.transformEntries(jarFile, getTransformers(accessWidener.getTargets()));
|
||||
}
|
||||
|
||||
private ZipEntryTransformerEntry[] getTransformers(Set<String> classes) {
|
||||
return classes.stream()
|
||||
.map(string -> new ZipEntryTransformerEntry(string.replaceAll("\\.", "/") + ".class", getTransformer(string)))
|
||||
.toArray(ZipEntryTransformerEntry[]::new);
|
||||
}
|
||||
|
||||
private ZipEntryTransformer getTransformer(String className) {
|
||||
return new ByteArrayZipEntryTransformer() {
|
||||
@Override
|
||||
protected byte[] transform(ZipEntry zipEntry, byte[] input) {
|
||||
ClassReader reader = new ClassReader(input);
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
ClassVisitor classVisitor = AccessWidenerClassVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener);
|
||||
|
||||
logger.info("Applying access widener to " + className);
|
||||
|
||||
reader.accept(classVisitor, 0);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
/**
|
||||
* Applies transitive access wideners that are inherited from mod and api dependencies.
|
||||
*/
|
||||
public class TransitiveAccessWidenerJarProcessor implements JarProcessor {
|
||||
private final Project project;
|
||||
private final LoomGradleExtension extension;
|
||||
|
||||
private final List<AccessWidenerFile> transitiveAccessWideners;
|
||||
|
||||
public TransitiveAccessWidenerJarProcessor(Project project) {
|
||||
this.project = project;
|
||||
this.extension = LoomGradleExtension.get(project);
|
||||
|
||||
transitiveAccessWideners = getTransitiveAccessWideners();
|
||||
|
||||
extension.addTransitiveAccessWideners(transitiveAccessWideners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return transitiveAccessWideners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
Preconditions.checkArgument(!isEmpty());
|
||||
|
||||
return "loom:transitive_access_wideners:" + transitiveAccessWideners.hashCode();
|
||||
}
|
||||
|
||||
private List<AccessWidenerFile> getTransitiveAccessWideners() {
|
||||
List<AccessWidenerFile> accessWideners = new ArrayList<>();
|
||||
|
||||
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
|
||||
// Only apply global AWs from mods that are part of the compile classpath
|
||||
if (!entry.compileClasspath()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<File> artifacts = extension.getLazyConfigurationProvider(entry.sourceConfiguration())
|
||||
.get()
|
||||
.resolve();
|
||||
|
||||
for (File artifact : artifacts) {
|
||||
AccessWidenerFile accessWidener = AccessWidenerFile.fromModJar(artifact.toPath());
|
||||
|
||||
if (accessWidener == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TransitiveDetectorVisitor.isTransitive(accessWidener.content())) {
|
||||
// AW does not contain anything transitive, skip over it
|
||||
continue;
|
||||
}
|
||||
|
||||
accessWideners.add(accessWidener);
|
||||
}
|
||||
}
|
||||
|
||||
return accessWideners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(File file) {
|
||||
Preconditions.checkArgument(!isEmpty());
|
||||
|
||||
AccessWidener accessWidener = createAccessWidener();
|
||||
AccessWidenerTransformer transformer = new AccessWidenerTransformer(project.getLogger(), accessWidener);
|
||||
transformer.apply(file);
|
||||
}
|
||||
|
||||
private AccessWidener createAccessWidener() {
|
||||
AccessWidener accessWidener = new AccessWidener();
|
||||
// For other mods, only consider transitive AWs and remap from intermediary->named
|
||||
TinyRemapper tinyRemapper = createTinyRemapper();
|
||||
|
||||
try {
|
||||
AccessWidenerRemapper remappingVisitor = new AccessWidenerRemapper(
|
||||
accessWidener,
|
||||
tinyRemapper.getRemapper(),
|
||||
MappingsNamespace.INTERMEDIARY.toString(),
|
||||
MappingsNamespace.NAMED.toString()
|
||||
);
|
||||
AccessWidenerReader transitiveReader = new AccessWidenerReader(new TransitiveOnlyFilter(remappingVisitor));
|
||||
|
||||
for (AccessWidenerFile accessWidenerFile : transitiveAccessWideners) {
|
||||
project.getLogger().info("Reading transitive access widener from {}", accessWidenerFile.modId());
|
||||
transitiveReader.read(accessWidenerFile.content());
|
||||
}
|
||||
} finally {
|
||||
tinyRemapper.finish();
|
||||
}
|
||||
|
||||
return accessWidener;
|
||||
}
|
||||
|
||||
private TinyRemapper createTinyRemapper() {
|
||||
try {
|
||||
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(project, "intermediary", "named");
|
||||
|
||||
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(project));
|
||||
tinyRemapper.readClassPath(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
|
||||
|
||||
return tinyRemapper;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to create tiny remapper for intermediary->named", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalid(File file) {
|
||||
// The hash is handled by getId()
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class TransitiveDetectorVisitor implements AccessWidenerVisitor {
|
||||
private boolean transitive = false;
|
||||
|
||||
@Override
|
||||
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTransitive(byte[] content) {
|
||||
if (AccessWidenerReader.readVersion(content) < 2) {
|
||||
// Transitive AWs are only in v2 or higher, so we can save parsing the file to find out...
|
||||
return false;
|
||||
}
|
||||
|
||||
TransitiveDetectorVisitor transitiveDetector = new TransitiveDetectorVisitor();
|
||||
new AccessWidenerReader(transitiveDetector).read(content);
|
||||
return transitiveDetector.transitive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public final class TransitiveAccessWidenerMappingsProcessor {
|
||||
private TransitiveAccessWidenerMappingsProcessor() {
|
||||
}
|
||||
|
||||
public static void process(Path inputMappings, Path outputMappings, List<AccessWidenerFile> accessWideners, Logger logger) {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(inputMappings, StandardCharsets.UTF_8)) {
|
||||
MappingReader.read(reader, new MappingSourceNsSwitch(mappingTree, MappingsNamespace.INTERMEDIARY.toString()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read mappings", e);
|
||||
}
|
||||
|
||||
if (!MappingsNamespace.INTERMEDIARY.toString().equals(mappingTree.getSrcNamespace())) {
|
||||
throw new IllegalStateException("Mapping tree must have intermediary src mappings not " + mappingTree.getSrcNamespace());
|
||||
}
|
||||
|
||||
for (AccessWidenerFile accessWidener : accessWideners) {
|
||||
MappingCommentVisitor mappingCommentVisitor = new MappingCommentVisitor(accessWidener.modId(), mappingTree, logger);
|
||||
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(new TransitiveOnlyFilter(mappingCommentVisitor));
|
||||
accessWidenerReader.read(accessWidener.content());
|
||||
}
|
||||
|
||||
try (Writer writer = Files.newBufferedWriter(outputMappings, StandardCharsets.UTF_8)) {
|
||||
Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false);
|
||||
mappingTree.accept(new MappingSourceNsSwitch(tiny2Writer, MappingsNamespace.NAMED.toString()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to write mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree, Logger logger) implements AccessWidenerVisitor {
|
||||
@Override
|
||||
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(name);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
classMapping.setComment(appendComment(classMapping.getComment(), access));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
// Access is also applied to the class, so also add the comment to the class
|
||||
visitClass(owner, access, transitive);
|
||||
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor);
|
||||
|
||||
if (methodMapping == null) {
|
||||
logger.warn("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
methodMapping.setComment(appendComment(methodMapping.getComment(), access));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
// Access is also applied to the class, so also add the comment to the class
|
||||
visitClass(owner, access, transitive);
|
||||
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor);
|
||||
|
||||
if (fieldMapping == null) {
|
||||
logger.warn("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
fieldMapping.setComment(appendComment(fieldMapping.getComment(), access));
|
||||
}
|
||||
|
||||
private String appendComment(String comment, AccessWidenerReader.AccessType access) {
|
||||
if (comment == null) {
|
||||
comment = "";
|
||||
} else {
|
||||
comment += "\n";
|
||||
}
|
||||
|
||||
comment += "Access widened by %s to %s".formatted(modId(), access);
|
||||
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,9 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.mods;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -56,19 +52,19 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerWriter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
|
||||
import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.LoggerFilter;
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.srg.AtRemapper;
|
||||
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
@@ -107,7 +103,7 @@ public class ModProcessor {
|
||||
private static void stripNestedJars(File file) {
|
||||
if (!ZipUtil.containsEntry(file, "fabric.mod.json")) return;
|
||||
// Strip out all contained jar info as we dont want loader to try and load the jars contained in dev.
|
||||
ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
|
||||
ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
|
||||
@Override
|
||||
protected String transform(ZipEntry zipEntry, String input) {
|
||||
JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
|
||||
@@ -117,29 +113,28 @@ public class ModProcessor {
|
||||
}))});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remap another mod's access widener from intermediary to named, so that loader can apply it in our dev-env.
|
||||
*/
|
||||
private static byte[] remapAccessWidener(byte[] input, Remapper remapper) {
|
||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(input), StandardCharsets.UTF_8))) {
|
||||
AccessWidener accessWidener = new AccessWidener();
|
||||
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener);
|
||||
accessWidenerReader.read(bufferedReader);
|
||||
int version = AccessWidenerReader.readVersion(input);
|
||||
|
||||
AccessWidenerRemapper accessWidenerRemapper = new AccessWidenerRemapper(accessWidener, remapper, "named");
|
||||
AccessWidener remapped = accessWidenerRemapper.remap();
|
||||
AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped);
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
accessWidenerWriter.write(writer);
|
||||
return writer.toString().getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
AccessWidenerWriter writer = new AccessWidenerWriter(version);
|
||||
AccessWidenerRemapper awRemapper = new AccessWidenerRemapper(
|
||||
writer,
|
||||
remapper,
|
||||
MappingsNamespace.INTERMEDIARY.toString(),
|
||||
MappingsNamespace.NAMED.toString()
|
||||
);
|
||||
AccessWidenerReader reader = new AccessWidenerReader(awRemapper);
|
||||
reader.read(input);
|
||||
return writer.write();
|
||||
}
|
||||
|
||||
private static void remapJars(Project project, List<ModDependencyInfo> processList) throws IOException {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
String fromM = extension.isForge() ? "srg" : "intermediary";
|
||||
String toM = "named";
|
||||
String fromM = extension.isForge() ? MappingsNamespace.SRG.toString() : MappingsNamespace.INTERMEDIARY.toString();
|
||||
String toM = MappingsNamespace.NAMED.toString();
|
||||
|
||||
MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider();
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
@@ -158,7 +153,7 @@ public class ModProcessor {
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.logger(project.getLogger()::lifecycle)
|
||||
.logUnknownInvokeDynamic(false)
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false))
|
||||
.withMappings(TinyRemapperHelper.create(mappings, fromM, toM, false))
|
||||
.renameInvalidLocals(false)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -25,12 +25,15 @@
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
|
||||
|
||||
public class GradleMappingContext implements MappingContext {
|
||||
@@ -45,9 +48,14 @@ public class GradleMappingContext implements MappingContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public File mavenFile(String mavenNotation) {
|
||||
Configuration configuration = project.getConfigurations().detachedConfiguration(project.getDependencies().create(mavenNotation));
|
||||
return configuration.getSingleFile();
|
||||
public Path resolveDependency(Dependency dependency) {
|
||||
Configuration configuration = project.getConfigurations().detachedConfiguration(dependency);
|
||||
return configuration.getSingleFile().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path resolveMavenDependency(String mavenNotation) {
|
||||
return resolveDependency(project.getDependencies().create(mavenNotation));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,8 +69,8 @@ public class GradleMappingContext implements MappingContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public File workingDirectory(String name) {
|
||||
return new File(minecraftProvider().dir("layered/working_dir/" + workingDirName), name);
|
||||
public Path workingDirectory(String name) {
|
||||
return new File(minecraftProvider().dir("layered/working_dir/" + workingDirName), name).toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,8 @@ package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
|
||||
public record LayeredMappingSpec(List<MappingsSpec<?>> layers) {
|
||||
public String getVersion() {
|
||||
// TODO something better?
|
||||
|
||||
@@ -31,13 +31,17 @@ import java.util.List;
|
||||
import org.gradle.api.Action;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.ParchmentMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.crane.CraneMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilderImpl;
|
||||
|
||||
public class LayeredMappingSpecBuilder {
|
||||
public class LayeredMappingSpecBuilderImpl implements LayeredMappingSpecBuilder {
|
||||
private final List<MappingsSpec<?>> layers = new LinkedList<>();
|
||||
@Nullable
|
||||
private final LoomGradleExtensionAPI extension;
|
||||
@@ -46,6 +50,9 @@ public class LayeredMappingSpecBuilder {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayeredMappingSpecBuilder addLayer(MappingsSpec<?> mappingSpec) {
|
||||
layers.add(mappingSpec);
|
||||
public LayeredMappingSpecBuilder officialMojangMappings() {
|
||||
layers.add(new MojangMappingsSpec(() -> extension != null && extension.isSilentMojangMappingsLicenseEnabled()));
|
||||
return this;
|
||||
@@ -56,11 +63,16 @@ public class LayeredMappingSpecBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) {
|
||||
ParchmentMappingsSpecBuilder builder = ParchmentMappingsSpecBuilder.builder(mavenNotation);
|
||||
@Override
|
||||
public LayeredMappingSpecBuilder officialMojangMappings() {
|
||||
return addLayer(new MojangMappingsSpec());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action) {
|
||||
ParchmentMappingsSpecBuilderImpl builder = ParchmentMappingsSpecBuilderImpl.builder(FileSpec.create(object));
|
||||
action.execute(builder);
|
||||
layers.add(builder.build());
|
||||
return this;
|
||||
return addLayer(builder.build());
|
||||
}
|
||||
|
||||
public LayeredMappingSpecBuilder crane(String mavenNotation) {
|
||||
@@ -54,6 +54,8 @@ import org.zeroturnaround.zip.ZipEntrySource;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.adapter.MappingDstNsReorder;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
@@ -87,8 +89,8 @@ public class LayeredMappingsDependency extends AbstractModuleDependency implemen
|
||||
try (Writer writer = new StringWriter()) {
|
||||
Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false);
|
||||
|
||||
MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingNamespace.NAMED.stringValue()));
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue(), true);
|
||||
MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingsNamespace.NAMED.toString()));
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingsNamespace.INTERMEDIARY.toString(), true);
|
||||
mappings.accept(nsSwitch);
|
||||
|
||||
Files.deleteIfExists(mappingsFile);
|
||||
|
||||
@@ -28,6 +28,10 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
@@ -55,7 +59,7 @@ public class LayeredMappingsProcessor {
|
||||
visitedLayers.add(layer.getClass());
|
||||
|
||||
// We have to rebuild a new tree to work on when a layer doesnt merge into layered
|
||||
boolean rebuild = layer.getSourceNamespace() != MappingNamespace.NAMED;
|
||||
boolean rebuild = layer.getSourceNamespace() != MappingsNamespace.NAMED;
|
||||
MemoryMappingTree workingTree;
|
||||
|
||||
if (rebuild) {
|
||||
@@ -63,7 +67,7 @@ public class LayeredMappingsProcessor {
|
||||
|
||||
// This can be null on the first layer
|
||||
if (mappingTree.getSrcNamespace() != null) {
|
||||
var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().stringValue());
|
||||
var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().toString());
|
||||
mappingTree.accept(sourceNsSwitch);
|
||||
}
|
||||
|
||||
@@ -80,7 +84,7 @@ public class LayeredMappingsProcessor {
|
||||
|
||||
if (rebuild) {
|
||||
mappingTree = new MemoryMappingTree();
|
||||
workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingNamespace.NAMED.stringValue()));
|
||||
workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingsNamespace.NAMED.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2020 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.fabricmc.loom.util.StaticPathWatcher;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public final class MappingsCache {
|
||||
public static final MappingsCache INSTANCE = new MappingsCache();
|
||||
|
||||
private final Map<Path, SoftReference<TinyTree>> mappingsCache = new HashMap<>();
|
||||
|
||||
// TODO: loom doesn't actually use new mappings when the mappings change until the gradle daemons are stopped
|
||||
public TinyTree get(Path mappingsPath) throws IOException {
|
||||
mappingsPath = mappingsPath.toAbsolutePath();
|
||||
|
||||
if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
|
||||
mappingsCache.remove(mappingsPath);
|
||||
}
|
||||
|
||||
SoftReference<TinyTree> ref = mappingsCache.get(mappingsPath);
|
||||
|
||||
if (ref != null && ref.get() != null) {
|
||||
return ref.get();
|
||||
} else {
|
||||
try (BufferedReader reader = Files.newBufferedReader(mappingsPath)) {
|
||||
TinyTree mappings = TinyMappingFactory.loadWithDetection(reader);
|
||||
ref = new SoftReference<>(mappings);
|
||||
mappingsCache.put(mappingsPath, ref);
|
||||
return mappings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
mappingsCache.clear();
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
@@ -54,8 +55,10 @@ import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
@@ -69,10 +72,10 @@ import net.fabricmc.loom.util.srg.MCPReader;
|
||||
import net.fabricmc.loom.util.srg.SrgMerger;
|
||||
import net.fabricmc.loom.util.srg.SrgNamedWriter;
|
||||
import net.fabricmc.mapping.reader.v2.TinyMetadata;
|
||||
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
@@ -103,13 +106,14 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
private Path unpickDefinitions;
|
||||
private boolean hasUnpickDefinitions;
|
||||
private UnpickMetadata unpickMetadata;
|
||||
private MemoryMappingTree mappingTree;
|
||||
|
||||
public MappingsProviderImpl(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
public TinyTree getMappings() throws IOException {
|
||||
return MappingsCache.INSTANCE.get(tinyMappings);
|
||||
public MemoryMappingTree getMappings() throws IOException {
|
||||
return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read");
|
||||
}
|
||||
|
||||
public TinyTree getMappingsWithSrg() throws IOException {
|
||||
@@ -148,6 +152,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
patchedProvider.provide(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
mappingTree = readMappings();
|
||||
manipulateMappings(mappingsJar.toPath());
|
||||
|
||||
if (getExtension().shouldGenerateSrgTiny()) {
|
||||
@@ -197,6 +202,14 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
extension.getGameJarProcessors().add(new AccessWidenerJarProcessor(getProject()));
|
||||
}
|
||||
|
||||
if (extension.getEnableTransitiveAccessWideners().get()) {
|
||||
TransitiveAccessWidenerJarProcessor transitiveAccessWidenerJarProcessor = new TransitiveAccessWidenerJarProcessor(getProject());
|
||||
|
||||
if (!transitiveAccessWidenerJarProcessor.isEmpty()) {
|
||||
extension.getGameJarProcessors().add(transitiveAccessWidenerJarProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
extension.getAccessWidenerPath().finalizeValue();
|
||||
extension.getGameJarProcessors().finalizeValue();
|
||||
JarProcessorManager processorManager = new JarProcessorManager(extension.getGameJarProcessors().get());
|
||||
@@ -305,6 +318,12 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
}
|
||||
}
|
||||
|
||||
private MemoryMappingTree readMappings() throws IOException {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
MappingReader.read(tinyMappings, mappingTree);
|
||||
return mappingTree;
|
||||
}
|
||||
|
||||
private void readAndMergeMCP(Path mcpJar, Consumer<Runnable> postPopulationScheduler) throws Exception {
|
||||
Path intermediaryTinyPath = getIntermediaryTiny();
|
||||
SrgProvider provider = getExtension().getSrgProvider();
|
||||
@@ -334,9 +353,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
|
||||
private static boolean areMappingsV2(Path path) throws IOException {
|
||||
try (BufferedReader reader = Files.newBufferedReader(path)) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException | NoSuchFileException e) {
|
||||
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
|
||||
} catch (NoSuchFileException e) {
|
||||
// TODO: just check the mappings version when Parser supports V1 in readMetadata()
|
||||
return false;
|
||||
}
|
||||
@@ -354,10 +372,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
private static boolean doesJarContainV2Mappings(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
|
||||
TinyV2Factory.readMetadata(reader);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -411,7 +426,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
project.getLogger().info(":merging mappings");
|
||||
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tree, MappingNamespace.OFFICIAL.stringValue());
|
||||
MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tree, MappingsNamespace.OFFICIAL.toString());
|
||||
readIntermediaryTree().accept(sourceNsSwitch);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(from, StandardCharsets.UTF_8)) {
|
||||
@@ -427,7 +442,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
|
||||
private MemoryMappingTree readIntermediaryTree() throws IOException {
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true);
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
@@ -451,7 +466,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
|
||||
runCommand(command, intermediaryMappings.toAbsolutePath().toString(),
|
||||
yarnMappings.toAbsolutePath().toString(),
|
||||
newMergedMappings.toAbsolutePath().toString(),
|
||||
"intermediary", "official");
|
||||
MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.OFFICIAL.toString());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString()
|
||||
+ " with mappings from " + yarnMappings, e);
|
||||
|
||||
@@ -32,22 +32,22 @@ import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
|
||||
public record IntermediaryMappingLayer(Supplier<File> tinyFile) implements MappingLayer {
|
||||
@Override
|
||||
public MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.OFFICIAL;
|
||||
public MappingsNamespace getSourceNamespace() {
|
||||
return MappingsNamespace.OFFICIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
// Populate named with intermediary and add Add a "named" namespace
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true);
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(tinyFile().get().toPath(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.intermediary;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
|
||||
public record IntermediaryMappingsSpec() implements MappingsSpec<IntermediaryMappingLayer> {
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
package net.fabricmc.loom.configuration.providers.mappings.mojmap;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -35,8 +34,8 @@ import java.util.List;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer;
|
||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||
@@ -47,33 +46,33 @@ import net.fabricmc.mappingio.format.ProGuardReader;
|
||||
public record MojangMappingLayer(String minecraftVersion,
|
||||
MinecraftVersionMeta.Download clientDownload,
|
||||
MinecraftVersionMeta.Download serverDownload,
|
||||
File workingDir,
|
||||
Path workingDir,
|
||||
Logger logger,
|
||||
MojangMappingsSpec.SilenceLicenseOption silenceLicense) implements MappingLayer {
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
var clientMappings = new File(workingDir(), "%s.client.txt".formatted(minecraftVersion));
|
||||
var serverMappings = new File(workingDir(), "%s.server.txt".formatted(minecraftVersion));
|
||||
Path clientMappings = workingDir().resolve("%s.client.txt".formatted(minecraftVersion));
|
||||
Path serverMappings = workingDir().resolve("%s.server.txt".formatted(minecraftVersion));
|
||||
|
||||
download(clientMappings, serverMappings);
|
||||
|
||||
if (!silenceLicense.isSilent()) {
|
||||
printMappingsLicense(clientMappings.toPath());
|
||||
printMappingsLicense(clientMappings);
|
||||
}
|
||||
|
||||
// Make official the source namespace
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingNamespace.OFFICIAL.stringValue());
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingsNamespace.OFFICIAL.toString());
|
||||
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings.toPath(), StandardCharsets.UTF_8);
|
||||
BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings.toPath(), StandardCharsets.UTF_8)) {
|
||||
ProGuardReader.read(clientBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch);
|
||||
ProGuardReader.read(serverBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch);
|
||||
try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8);
|
||||
BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)) {
|
||||
ProGuardReader.read(clientBufferedReader, MappingsNamespace.NAMED.toString(), MappingsNamespace.OFFICIAL.toString(), nsSwitch);
|
||||
ProGuardReader.read(serverBufferedReader, MappingsNamespace.NAMED.toString(), MappingsNamespace.OFFICIAL.toString(), nsSwitch);
|
||||
}
|
||||
}
|
||||
|
||||
private void download(File clientMappings, File serverMappings) throws IOException {
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings, clientDownload().sha1(), logger(), false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings, serverDownload().sha1(), logger(), false);
|
||||
private void download(Path clientMappings, Path serverMappings) throws IOException {
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings.toFile(), clientDownload().sha1(), logger(), false);
|
||||
HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings.toFile(), serverDownload().sha1(), logger(), false);
|
||||
}
|
||||
|
||||
private void printMappingsLicense(Path clientMappings) {
|
||||
@@ -95,8 +94,8 @@ public record MojangMappingLayer(String minecraftVersion,
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingNamespace getSourceNamespace() {
|
||||
return MappingNamespace.OFFICIAL;
|
||||
public MappingsNamespace getSourceNamespace() {
|
||||
return MappingsNamespace.OFFICIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.mojmap;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||
|
||||
public record MojangMappingsSpec(SilenceLicenseOption silenceLicense) implements MappingsSpec<MojangMappingLayer> {
|
||||
|
||||
@@ -24,19 +24,19 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
|
||||
public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) implements MappingLayer {
|
||||
public record ParchmentMappingLayer(Path parchmentFile, boolean removePrefix) implements MappingLayer {
|
||||
private static final String PARCHMENT_DATA_FILE_NAME = "parchment.json";
|
||||
|
||||
@Override
|
||||
@@ -47,11 +47,11 @@ public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) im
|
||||
mappingVisitor = new ParchmentPrefixStripingMappingVisitor(mappingVisitor);
|
||||
}
|
||||
|
||||
parchmentData.visit(mappingVisitor, MappingNamespace.NAMED.stringValue());
|
||||
parchmentData.visit(mappingVisitor, MappingsNamespace.NAMED.toString());
|
||||
}
|
||||
|
||||
private ParchmentTreeV1 getParchmentData() throws IOException {
|
||||
try (var zipFile = new ZipFile(parchmentFile())) {
|
||||
try (var zipFile = new ZipFile(parchmentFile().toFile())) {
|
||||
ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME);
|
||||
Objects.requireNonNull(zipFileEntry, "Could not find %s in parchment data file".formatted(PARCHMENT_DATA_FILE_NAME));
|
||||
|
||||
|
||||
@@ -24,12 +24,13 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
|
||||
public record ParchmentMappingsSpec(String mavenNotation, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> {
|
||||
public record ParchmentMappingsSpec(FileSpec fileSpec, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> {
|
||||
@Override
|
||||
public ParchmentMappingLayer createLayer(MappingContext context) {
|
||||
return new ParchmentMappingLayer(context.mavenFile(mavenNotation()), removePrefix());
|
||||
return new ParchmentMappingLayer(fileSpec.get(context), removePrefix());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,25 +24,29 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.parchment;
|
||||
|
||||
public class ParchmentMappingsSpecBuilder {
|
||||
private final String mavenNotation;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.ParchmentMappingsSpecBuilder;
|
||||
|
||||
public class ParchmentMappingsSpecBuilderImpl implements ParchmentMappingsSpecBuilder {
|
||||
private final FileSpec fileSpec;
|
||||
|
||||
private boolean removePrefix;
|
||||
|
||||
private ParchmentMappingsSpecBuilder(String mavenNotation) {
|
||||
this.mavenNotation = mavenNotation;
|
||||
private ParchmentMappingsSpecBuilderImpl(FileSpec fileSpec) {
|
||||
this.fileSpec = fileSpec;
|
||||
}
|
||||
|
||||
public static ParchmentMappingsSpecBuilder builder(String depNotation) {
|
||||
return new ParchmentMappingsSpecBuilder(depNotation);
|
||||
public static ParchmentMappingsSpecBuilderImpl builder(FileSpec fileSpec) {
|
||||
return new ParchmentMappingsSpecBuilderImpl(fileSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix) {
|
||||
this.removePrefix = removePrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParchmentMappingsSpec build() {
|
||||
return new ParchmentMappingsSpec(mavenNotation, removePrefix);
|
||||
return new ParchmentMappingsSpec(fileSpec, removePrefix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.SelfResolvingDependency;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
|
||||
public record DependencyFileSpec(Dependency dependency) implements FileSpec {
|
||||
@Override
|
||||
public Path get(MappingContext context) {
|
||||
if (dependency instanceof SelfResolvingDependency selfResolvingDependency) {
|
||||
Set<File> files = selfResolvingDependency.resolve();
|
||||
|
||||
if (files.size() == 0) {
|
||||
throw new RuntimeException("SelfResolvingDependency (%s) resolved no files".formatted(selfResolvingDependency.toString()));
|
||||
} else if (files.size() > 1) {
|
||||
throw new RuntimeException("SelfResolvingDependency (%s) resolved too many files (%d) only 1 is expected".formatted(selfResolvingDependency.toString(), files.size()));
|
||||
}
|
||||
|
||||
return files.iterator().next().toPath();
|
||||
}
|
||||
|
||||
return context.resolveDependency(dependency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(dependency.getGroup(), dependency.getName(), dependency.getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DependencyFileSpec other) {
|
||||
return other.dependency().contentEquals(this.dependency());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
|
||||
public class LocalFileSpec implements FileSpec {
|
||||
private final File file;
|
||||
private final int hash;
|
||||
|
||||
public LocalFileSpec(File file) {
|
||||
this.file = file;
|
||||
this.hash = calculateHashCode();
|
||||
}
|
||||
|
||||
private int calculateHashCode() {
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("Could not find %s, it must be present at spec creation time to calculate mappings hash".formatted(file.getAbsolutePath()));
|
||||
}
|
||||
|
||||
// Use the file hash as part of the spec, this means if the input file changes the mappings will be re-generated.
|
||||
return Objects.hash(Arrays.hashCode(Checksum.sha256(file)), file.getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path get(MappingContext context) {
|
||||
return file.toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.utils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
|
||||
public record MavenFileSpec(String dependencyNotation) implements FileSpec {
|
||||
@Override
|
||||
public Path get(MappingContext context) {
|
||||
return context.resolveMavenDependency(dependencyNotation);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import dev.architectury.tinyremapper.TinyRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
@@ -56,7 +57,7 @@ import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.OperatingSystem;
|
||||
import net.fabricmc.loom.util.ThreadingUtils;
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.srg.AtRemapper;
|
||||
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
|
||||
import net.fabricmc.loom.util.srg.InnerClassRemapper;
|
||||
@@ -251,7 +252,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
assetsOut(inputForge, forgeAssets);
|
||||
}
|
||||
|
||||
remap(remapper, vanilla, forge, "official");
|
||||
remap(remapper, vanilla, forge, MappingsNamespace.OFFICIAL.toString());
|
||||
}
|
||||
|
||||
public static class Info {
|
||||
@@ -273,9 +274,9 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
public void remap(TinyRemapper remapper, Info vanilla, @Nullable Info forge, String fromM) throws IOException {
|
||||
Set<String> classNames = getExtension().isForge() ? InnerClassRemapper.readClassNames(vanilla.input) : null;
|
||||
|
||||
for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) {
|
||||
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;
|
||||
for (String toM : getExtension().isForge() ? Arrays.asList(MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString()) : Arrays.asList(MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.NAMED.toString())) {
|
||||
Path output = MappingsNamespace.NAMED.toString().equals(toM) ? vanilla.outputMapped : MappingsNamespace.SRG.toString().equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary;
|
||||
Path outputForge = forge == null ? null : MappingsNamespace.NAMED.toString().equals(toM) ? forge.outputMapped : MappingsNamespace.SRG.toString().equals(toM) ? forge.outputSrg : forge.outputIntermediary;
|
||||
InputTag vanillaTag = remapper.createInputTag();
|
||||
InputTag forgeTag = remapper.createInputTag();
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
@@ -294,6 +295,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||
OutputRemappingHandler.remap(remapper, forge.assets, outputForge, null, forgeTag);
|
||||
}
|
||||
|
||||
// TODO TinyRemapperHelper
|
||||
getProject().getLogger().lifecycle(":remapped minecraft (TinyRemapper, " + fromM + " -> " + toM + ") in " + stopwatch);
|
||||
remapper.removeInput();
|
||||
|
||||
|
||||
@@ -126,12 +126,12 @@ public class LineNumberRemapper {
|
||||
|
||||
reader.accept(new LineNumberVisitor(Constants.ASM_VERSION, writer, lineMap.get(idx)), 0);
|
||||
Files.write(dst, writer.toByteArray());
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,9 +29,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||
import org.jetbrains.java.decompiler.struct.StructField;
|
||||
@@ -40,48 +38,29 @@ import org.jetbrains.java.decompiler.struct.StructRecordComponent;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.fabricmc.fernflower.api.IFabricJavadocProvider;
|
||||
import net.fabricmc.mapping.tree.ClassDef;
|
||||
import net.fabricmc.mapping.tree.FieldDef;
|
||||
import net.fabricmc.mapping.tree.MethodDef;
|
||||
import net.fabricmc.mapping.tree.ParameterDef;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.mappings.EntryTriple;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class TinyJavadocProvider implements IFabricJavadocProvider {
|
||||
private final Map<String, ClassDef> classes = new HashMap<>();
|
||||
private final Map<EntryTriple, FieldDef> fields = new HashMap<>();
|
||||
private final Map<EntryTriple, MethodDef> methods = new HashMap<>();
|
||||
|
||||
private final String namespace = "named";
|
||||
private final MappingTree mappingTree;
|
||||
|
||||
public TinyJavadocProvider(File tinyFile) {
|
||||
final TinyTree mappings = readMappings(tinyFile);
|
||||
|
||||
for (ClassDef classDef : mappings.getClasses()) {
|
||||
final String className = classDef.getName(namespace);
|
||||
classes.put(className, classDef);
|
||||
|
||||
for (FieldDef fieldDef : classDef.getFields()) {
|
||||
fields.put(new EntryTriple(className, fieldDef.getName(namespace), fieldDef.getDescriptor(namespace)), fieldDef);
|
||||
}
|
||||
|
||||
for (MethodDef methodDef : classDef.getMethods()) {
|
||||
methods.put(new EntryTriple(className, methodDef.getName(namespace), methodDef.getDescriptor(namespace)), methodDef);
|
||||
}
|
||||
}
|
||||
mappingTree = readMappings(tinyFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassDoc(StructClass structClass) {
|
||||
ClassDef classDef = classes.get(structClass.qualifiedName);
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
|
||||
|
||||
if (classDef == null) {
|
||||
if (classMapping == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isRecord(structClass)) {
|
||||
return classDef.getComment();
|
||||
return classMapping.getComment();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,30 +70,30 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
|
||||
*/
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
if (classDef.getComment() != null) {
|
||||
parts.add(classDef.getComment());
|
||||
if (classMapping.getComment() != null) {
|
||||
parts.add(classMapping.getComment());
|
||||
}
|
||||
|
||||
boolean addedParam = false;
|
||||
|
||||
for (StructRecordComponent component : structClass.getRecordComponents()) {
|
||||
// The component will always match the field name and descriptor
|
||||
FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, component.getName(), component.getDescriptor()));
|
||||
MappingTree.FieldMapping fieldMapping = classMapping.getField(component.getName(), component.getDescriptor());
|
||||
|
||||
if (fieldDef == null) {
|
||||
if (fieldMapping == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String comment = fieldDef.getComment();
|
||||
String comment = fieldMapping.getComment();
|
||||
|
||||
if (comment != null) {
|
||||
if (!addedParam && classDef.getComment() != null) {
|
||||
if (!addedParam && classMapping.getComment() != null) {
|
||||
//Add a blank line before components when the class has a comment
|
||||
parts.add("");
|
||||
addedParam = true;
|
||||
}
|
||||
|
||||
parts.add(String.format("@param %s %s", fieldDef.getName(namespace), comment));
|
||||
parts.add(String.format("@param %s %s", fieldMapping.getName(MappingsNamespace.NAMED.toString()), comment));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,34 +111,47 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor()));
|
||||
return fieldDef != null ? fieldDef.getComment() : null;
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
|
||||
|
||||
if (classMapping == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MappingTree.FieldMapping fieldMapping = classMapping.getField(structField.getName(), structField.getDescriptor());
|
||||
|
||||
return fieldMapping != null ? fieldMapping.getComment() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodDoc(StructClass structClass, StructMethod structMethod) {
|
||||
MethodDef methodDef = methods.get(new EntryTriple(structClass.qualifiedName, structMethod.getName(), structMethod.getDescriptor()));
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
|
||||
|
||||
if (methodDef != null) {
|
||||
if (classMapping == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MappingTree.MethodMapping methodMapping = classMapping.getMethod(structMethod.getName(), structMethod.getDescriptor());
|
||||
|
||||
if (methodMapping != null) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
if (methodDef.getComment() != null) {
|
||||
parts.add(methodDef.getComment());
|
||||
if (methodMapping.getComment() != null) {
|
||||
parts.add(methodMapping.getComment());
|
||||
}
|
||||
|
||||
boolean addedParam = false;
|
||||
|
||||
for (ParameterDef param : methodDef.getParameters()) {
|
||||
String comment = param.getComment();
|
||||
for (MappingTree.MethodArgMapping argMapping : methodMapping.getArgs()) {
|
||||
String comment = argMapping.getComment();
|
||||
|
||||
if (comment != null) {
|
||||
if (!addedParam && methodDef.getComment() != null) {
|
||||
if (!addedParam && methodMapping.getComment() != null) {
|
||||
//Add a blank line before params when the method has a comment
|
||||
parts.add("");
|
||||
addedParam = true;
|
||||
}
|
||||
|
||||
parts.add(String.format("@param %s %s", param.getName(namespace), comment));
|
||||
parts.add(String.format("@param %s %s", methodMapping.getName(MappingsNamespace.NAMED.toString()), comment));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,9 +165,13 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TinyTree readMappings(File input) {
|
||||
private static MappingTree readMappings(File input) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(input.toPath())) {
|
||||
return TinyMappingFactory.loadWithDetection(reader);
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingTree, MappingsNamespace.NAMED.toString());
|
||||
MappingReader.read(reader, nsSwitch);
|
||||
|
||||
return mappingTree;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read mappings", e);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.gradle.api.tasks.SourceSet;
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.api.MixinExtensionAPI;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.api.ForgeExtensionAPI;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfig;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||
@@ -61,7 +62,7 @@ import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
|
||||
import net.fabricmc.loom.util.DeprecationHelper;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
@@ -84,6 +85,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
protected final Property<Boolean> remapArchives;
|
||||
protected final Property<String> customManifest;
|
||||
protected final Property<Boolean> setupRemappedVariants;
|
||||
protected final Property<Boolean> transitiveAccessWideners;
|
||||
|
||||
private final ModVersionParser versionParser;
|
||||
|
||||
@@ -122,6 +124,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
this.customManifest = project.getObjects().property(String.class);
|
||||
this.setupRemappedVariants = project.getObjects().property(Boolean.class)
|
||||
.convention(true);
|
||||
this.transitiveAccessWideners = project.getObjects().property(Boolean.class)
|
||||
.convention(true);
|
||||
this.transitiveAccessWideners.finalizeValueOnRead();
|
||||
|
||||
this.versionParser = new ModVersionParser(project);
|
||||
|
||||
@@ -174,7 +179,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
|
||||
@Override
|
||||
public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
|
||||
LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this);
|
||||
LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl(this);
|
||||
action.execute(builder);
|
||||
LayeredMappingSpec builtSpec = builder.build();
|
||||
return new LayeredMappingsDependency(new GradleMappingContext(getProject(), builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion());
|
||||
@@ -222,6 +227,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
return versionParser.getModVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property<Boolean> getEnableTransitiveAccessWideners() {
|
||||
return transitiveAccessWideners;
|
||||
}
|
||||
|
||||
protected abstract Project getProject();
|
||||
|
||||
protected abstract LoomFiles getFiles();
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
package net.fabricmc.loom.extension;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -45,6 +47,7 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.ForgeExtensionAPI;
|
||||
import net.fabricmc.loom.configuration.InstallerData;
|
||||
import net.fabricmc.loom.configuration.LoomDependencyManager;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
|
||||
@@ -59,6 +62,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
private final MappingSet[] srcMappingCache = new MappingSet[2];
|
||||
private final Mercury[] srcMercuryCache = new Mercury[2];
|
||||
private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
|
||||
private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>();
|
||||
|
||||
private LoomDependencyManager dependencyManager;
|
||||
private JarProcessorManager jarProcessorManager;
|
||||
@@ -176,6 +180,16 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||
return this.mixinApExtension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessWidenerFile> getTransitiveAccessWideners() {
|
||||
return transitiveAccessWideners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles) {
|
||||
transitiveAccessWideners.addAll(accessWidenerFiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMinecraftVersion() {
|
||||
return getMinecraftProvider().minecraftVersion();
|
||||
|
||||
@@ -45,11 +45,11 @@ import net.fabricmc.loom.api.ForgeExtensionAPI;
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.api.MixinExtensionAPI;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfig;
|
||||
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.util.DeprecationHelper;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
|
||||
@@ -163,6 +163,12 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
|
||||
throw new UnsupportedOperationException("Use loom extension");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property<Boolean> getEnableTransitiveAccessWideners() {
|
||||
reportDeprecation();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void silentMojangMappingsLicense() {
|
||||
reportDeprecation();
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -42,6 +43,8 @@ import org.gradle.api.tasks.TaskAction;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
|
||||
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerMappingsProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.decompilers.LineNumberRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -63,11 +66,10 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
@TaskAction
|
||||
public void doTask() throws Throwable {
|
||||
int threads = Runtime.getRuntime().availableProcessors();
|
||||
Path javaDocs = getExtension().getMappingsProvider().tinyMappings;
|
||||
Collection<Path> libraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
|
||||
.stream().map(File::toPath).collect(Collectors.toSet());
|
||||
.stream().map(File::toPath).collect(Collectors.toSet());
|
||||
|
||||
DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries);
|
||||
DecompilationMetadata metadata = new DecompilationMetadata(threads, getMappings(), libraries);
|
||||
Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath();
|
||||
Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath();
|
||||
Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath();
|
||||
@@ -93,7 +95,7 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
progressLogger.start("Adjusting line numbers", "linemap");
|
||||
|
||||
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(oldCompiledJar.toFile(), true);
|
||||
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) {
|
||||
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) {
|
||||
remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/"));
|
||||
}
|
||||
|
||||
@@ -121,6 +123,32 @@ public class GenerateSourcesTask extends AbstractLoomTask {
|
||||
return new File(path.substring(0, path.length() - 4) + suffix);
|
||||
}
|
||||
|
||||
private Path getMappings() {
|
||||
Path baseMappings = getExtension().getMappingsProvider().tinyMappings;
|
||||
|
||||
if (getExtension().getEnableTransitiveAccessWideners().get()) {
|
||||
List<AccessWidenerFile> accessWideners = getExtension().getTransitiveAccessWideners();
|
||||
|
||||
if (accessWideners.isEmpty()) {
|
||||
return baseMappings;
|
||||
}
|
||||
|
||||
Path outputMappings;
|
||||
|
||||
try {
|
||||
outputMappings = Files.createTempFile("loom-transitive-mappings", ".tiny");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to create temp file", e);
|
||||
}
|
||||
|
||||
TransitiveAccessWidenerMappingsProcessor.process(baseMappings, outputMappings, accessWideners, getProject().getLogger());
|
||||
|
||||
return outputMappings;
|
||||
}
|
||||
|
||||
return baseMappings;
|
||||
}
|
||||
|
||||
@InputFile
|
||||
public File getInputJar() {
|
||||
return inputJar;
|
||||
|
||||
@@ -24,14 +24,12 @@
|
||||
|
||||
package net.fabricmc.loom.task;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -49,14 +47,15 @@ import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.options.Option;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsJoiner;
|
||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class MigrateMappingsTask extends AbstractLoomTask {
|
||||
private Path inputDir;
|
||||
@@ -100,8 +99,8 @@ public class MigrateMappingsTask extends AbstractLoomTask {
|
||||
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
try {
|
||||
TinyTree currentMappings = mappingsProvider.getMappings();
|
||||
TinyTree targetMappings = getMappings(mappings);
|
||||
MemoryMappingTree currentMappings = mappingsProvider.getMappings();
|
||||
MemoryMappingTree targetMappings = getMappings(mappings);
|
||||
migrateMappings(project, extension, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings);
|
||||
project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
@@ -148,27 +147,25 @@ public class MigrateMappingsTask extends AbstractLoomTask {
|
||||
return Iterables.getOnlyElement(files);
|
||||
}
|
||||
|
||||
private static TinyTree getMappings(File mappings) throws IOException {
|
||||
Path temp = Files.createTempFile("mappings", ".tiny");
|
||||
private static MemoryMappingTree getMappings(File mappings) throws IOException {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(mappings.toPath(), (ClassLoader) null)) {
|
||||
Files.copy(fileSystem.getPath("mappings/mappings.tiny"), temp, StandardCopyOption.REPLACE_EXISTING);
|
||||
MappingReader.read(fileSystem.getPath("mappings/mappings.tiny"), mappingTree);
|
||||
}
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(temp)) {
|
||||
return TinyMappingFactory.loadWithDetection(reader);
|
||||
}
|
||||
return mappingTree;
|
||||
}
|
||||
|
||||
private static void migrateMappings(Project project, LoomGradleExtension extension, MinecraftMappedProvider minecraftMappedProvider,
|
||||
Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings
|
||||
Path inputDir, Path outputDir, MemoryMappingTree currentMappings, MemoryMappingTree targetMappings
|
||||
) throws IOException {
|
||||
project.getLogger().info(":joining mappings");
|
||||
|
||||
MappingSet mappingSet = new TinyMappingsJoiner(
|
||||
currentMappings, "named",
|
||||
targetMappings, "named",
|
||||
"intermediary"
|
||||
currentMappings, MappingsNamespace.NAMED.toString(),
|
||||
targetMappings, MappingsNamespace.NAMED.toString(),
|
||||
MappingsNamespace.INTERMEDIARY.toString()
|
||||
).read();
|
||||
|
||||
project.getLogger().lifecycle(":remapping");
|
||||
|
||||
@@ -86,6 +86,7 @@ import org.zeroturnaround.zip.transform.StreamZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.build.JarRemapper;
|
||||
import net.fabricmc.loom.build.MixinRefmapHelper;
|
||||
import net.fabricmc.loom.build.nesting.EmptyNestedJarProvider;
|
||||
@@ -95,12 +96,13 @@ import net.fabricmc.loom.build.nesting.NestedDependencyProvider;
|
||||
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
|
||||
import net.fabricmc.loom.build.nesting.NestedJarProvider;
|
||||
import net.fabricmc.loom.configuration.JarManifestConfiguration;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.ZipReprocessorUtil;
|
||||
import net.fabricmc.loom.util.aw2at.Aw2At;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
@@ -247,7 +249,7 @@ public class RemapJarTask extends Jar {
|
||||
if (isMainRemapTask) {
|
||||
jarRemapper.addToClasspath(getRemapClasspath());
|
||||
|
||||
jarRemapper.addMappings(TinyRemapperMappingsHelper.create(extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(), fromM, toM, false));
|
||||
jarRemapper.addMappings(TinyRemapperHelper.create(extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(), fromM, toM, false));
|
||||
}
|
||||
|
||||
for (File mixinMapFile : extension.getAllMixinMappings()) {
|
||||
@@ -272,15 +274,15 @@ public class RemapJarTask extends Jar {
|
||||
byte[] data;
|
||||
|
||||
try {
|
||||
data = accessWidenerJarProcessor.getRemappedAccessWidener(remapper);
|
||||
data = accessWidenerJarProcessor.getRemappedAccessWidener(remapper, toM);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to remap access widener");
|
||||
throw new RuntimeException("Failed to remap access widener", e);
|
||||
}
|
||||
|
||||
String awPath = accessWidenerJarProcessor.getAccessWidenerPath(remapData.input);
|
||||
Preconditions.checkNotNull(awPath, "Failed to find accessWidener in fabric.mod.json: " + remapData.input);
|
||||
AccessWidenerFile awFile = AccessWidenerFile.fromModJar(remapData.input);
|
||||
Preconditions.checkNotNull(awFile, "Failed to find accessWidener in fabric.mod.json: " + remapData.input);
|
||||
|
||||
return Pair.of(awPath, data);
|
||||
return Pair.of(awFile.name(), data);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -559,7 +561,8 @@ public class RemapJarTask extends Jar {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental // This only allows mod jars, proceed with care when trying to pass in configurations with projects, or something that depends on a task.
|
||||
@ApiStatus.Experimental
|
||||
// This only allows mod jars, proceed with care when trying to pass in configurations with projects, or something that depends on a task.
|
||||
public RemapJarTask include(Object... paths) {
|
||||
Collections.addAll(nestedPaths, paths);
|
||||
this.addNestedDependencies.set(true);
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
|
||||
public class RemapSourcesJarTask extends AbstractLoomTask {
|
||||
@@ -53,7 +54,7 @@ public class RemapSourcesJarTask extends AbstractLoomTask {
|
||||
if (sourceRemapper == null) {
|
||||
if (sourceNamespace.get().equals(targetNamespace.get())) {
|
||||
SourceRemapper.remapSources(getProject(), getInput().get().getAsFile(), getOutput().get().getAsFile(),
|
||||
targetNamespace.get().equals("named") ? SourceRemapper.intermediary(getProject()) : "named", targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get());
|
||||
targetNamespace.get().equals(MappingsNamespace.NAMED.toString()) ? SourceRemapper.intermediary(getProject()) : "named", targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get());
|
||||
} else {
|
||||
SourceRemapper.remapSources(getProject(), getInput().get().getAsFile(), getOutput().get().getAsFile(), sourceNamespace.get(), targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get());
|
||||
}
|
||||
|
||||
@@ -53,8 +53,6 @@ public class Constants {
|
||||
new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME)
|
||||
);
|
||||
|
||||
public static final String SOFTWARE_COMPONENT_NAME = "loom";
|
||||
|
||||
private Constants() {
|
||||
}
|
||||
|
||||
|
||||
@@ -40,11 +40,12 @@ import org.gradle.api.Project;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.gradle.ProgressLogger;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.stitch.util.StitchUtil;
|
||||
|
||||
public class SourceRemapper {
|
||||
@@ -184,7 +185,7 @@ public class SourceRemapper {
|
||||
|
||||
MappingSet mappings = extension.getOrCreateSrcMappingCache(id, () -> {
|
||||
try {
|
||||
TinyTree m = extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings();
|
||||
MemoryMappingTree m = extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings();
|
||||
project.getLogger().info(":loading " + from + " -> " + to + " source mappings");
|
||||
return new TinyMappingsReader(m, from, to).read();
|
||||
} catch (Exception e) {
|
||||
|
||||
108
src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java
Normal file
108
src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.tinyremapper.IMappingProvider;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
/**
|
||||
* Contains shortcuts to create tiny remappers using the mappings accessibly to the project.
|
||||
*/
|
||||
public final class TinyRemapperHelper {
|
||||
private static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>()
|
||||
.put("javax/annotation/Nullable", "org/jetbrains/annotations/Nullable")
|
||||
.put("javax/annotation/Nonnull", "org/jetbrains/annotations/NotNull")
|
||||
.put("javax/annotation/concurrent/Immutable", "org/jetbrains/annotations/Unmodifiable")
|
||||
.build();
|
||||
|
||||
private TinyRemapperHelper() {
|
||||
}
|
||||
|
||||
public static TinyRemapper getTinyRemapper(Project project, String fromM, String toM) throws IOException {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
return TinyRemapper.newRemapper()
|
||||
.withMappings(create(extension.getMappingsProvider().getMappings(), fromM, toM, true))
|
||||
.withMappings(out -> JSR_TO_JETBRAINS.forEach(out::acceptClass))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Path[] getMinecraftDependencies(Project project) {
|
||||
return project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
|
||||
.stream().map(File::toPath).toArray(Path[]::new);
|
||||
}
|
||||
|
||||
private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) {
|
||||
return new IMappingProvider.Member(className, memberName, descriptor);
|
||||
}
|
||||
|
||||
public static IMappingProvider create(MappingTree mappings, String from, String to, boolean remapLocalVariables) {
|
||||
return (acceptor) -> {
|
||||
for (MappingTree.ClassMapping classDef : mappings.getClasses()) {
|
||||
String className = classDef.getName(from);
|
||||
acceptor.acceptClass(className, classDef.getName(to));
|
||||
|
||||
for (MappingTree.FieldMapping field : classDef.getFields()) {
|
||||
acceptor.acceptField(memberOf(className, field.getName(from), field.getDesc(from)), field.getName(to));
|
||||
}
|
||||
|
||||
for (MappingTree.MethodMapping method : classDef.getMethods()) {
|
||||
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDesc(from));
|
||||
acceptor.acceptMethod(methodIdentifier, method.getName(to));
|
||||
|
||||
if (remapLocalVariables) {
|
||||
for (MappingTree.MethodArgMapping parameter : method.getArgs()) {
|
||||
String name = parameter.getName(to);
|
||||
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
acceptor.acceptMethodArg(methodIdentifier, parameter.getLvIndex(), name);
|
||||
}
|
||||
|
||||
for (MappingTree.MethodVarMapping localVariable : method.getVars()) {
|
||||
acceptor.acceptMethodVar(methodIdentifier, localVariable.getLvIndex(),
|
||||
localVariable.getStartOpIdx(), localVariable.getLvtRowIndex(),
|
||||
localVariable.getName(to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2019 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util;
|
||||
|
||||
import dev.architectury.tinyremapper.IMappingProvider;
|
||||
|
||||
import net.fabricmc.mapping.tree.ClassDef;
|
||||
import net.fabricmc.mapping.tree.FieldDef;
|
||||
import net.fabricmc.mapping.tree.LocalVariableDef;
|
||||
import net.fabricmc.mapping.tree.MethodDef;
|
||||
import net.fabricmc.mapping.tree.ParameterDef;
|
||||
import net.fabricmc.mapping.tree.TinyTree;
|
||||
|
||||
public class TinyRemapperMappingsHelper {
|
||||
private TinyRemapperMappingsHelper() { }
|
||||
|
||||
private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) {
|
||||
return new IMappingProvider.Member(className, memberName, descriptor);
|
||||
}
|
||||
|
||||
public static IMappingProvider create(TinyTree mappings, String from, String to, boolean remapLocalVariables) {
|
||||
return (acceptor) -> {
|
||||
for (ClassDef classDef : mappings.getClasses()) {
|
||||
String className = classDef.getName(from);
|
||||
acceptor.acceptClass(className, classDef.getName(to));
|
||||
|
||||
for (FieldDef field : classDef.getFields()) {
|
||||
acceptor.acceptField(memberOf(className, field.getName(from), field.getDescriptor(from)), field.getName(to));
|
||||
}
|
||||
|
||||
for (MethodDef method : classDef.getMethods()) {
|
||||
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDescriptor(from));
|
||||
acceptor.acceptMethod(methodIdentifier, method.getName(to));
|
||||
|
||||
if (remapLocalVariables) {
|
||||
for (ParameterDef parameter : method.getParameters()) {
|
||||
acceptor.acceptMethodArg(methodIdentifier, parameter.getLocalVariableIndex(), parameter.getName(to));
|
||||
}
|
||||
|
||||
for (LocalVariableDef localVariable : method.getLocalVariables()) {
|
||||
acceptor.acceptMethodVar(methodIdentifier, localVariable.getLocalVariableIndex(),
|
||||
localVariable.getLocalVariableStartOffset(), localVariable.getLocalVariableTableIndex(),
|
||||
localVariable.getName(to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user