aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuuxel <6596629+Juuxel@users.noreply.github.com>2021-09-10 21:08:41 +0300
committerGitHub <noreply@github.com>2021-09-11 02:08:41 +0800
commite1f5f3d6eb674b3513e7dd848c202ef7479a70a8 (patch)
treed7e1c58e1fad0ef3711e1e6143e7fd9fadebe576
parentaaacd23c8bdd2c52c727ab7119afd8dd968f762a (diff)
downloadarchitectury-loom-e1f5f3d6eb674b3513e7dd848c202ef7479a70a8.tar.gz
architectury-loom-e1f5f3d6eb674b3513e7dd848c202ef7479a70a8.tar.bz2
architectury-loom-e1f5f3d6eb674b3513e7dd848c202ef7479a70a8.zip
Convert AWs on Forge to ATs in RemapJarTask (#24)
* Aw2At * Hook Aw2At up to remapJar * Checkstyle * Checkstyle, part II * Now it's Spotless' turn * Remap the resulting AT * you see, this is why mojmap is bad * Inject(method = "<init>") * Use file systems because ZipUtil is bad * Make it false by default * Add integ tests for aw2at * spotless please * fix year
-rw-r--r--src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java1
-rw-r--r--src/main/java/net/fabricmc/loom/api/ForgeExtensionAPI.java51
-rw-r--r--src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java12
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java12
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java6
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java18
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java5
-rw-r--r--src/main/java/net/fabricmc/loom/extension/ForgeExtensionImpl.java54
-rw-r--r--src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java23
-rw-r--r--src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java11
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java13
-rw-r--r--src/main/java/net/fabricmc/loom/task/RemapJarTask.java73
-rw-r--r--src/main/java/net/fabricmc/loom/util/Constants.java5
-rw-r--r--src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java25
-rw-r--r--src/main/java/net/fabricmc/loom/util/ModPlatform.java24
-rw-r--r--src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java122
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java3
-rw-r--r--src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java24
-rw-r--r--src/test/groovy/net/fabricmc/loom/test/integration/forge/Aw2AtTest.groovy50
-rw-r--r--src/test/groovy/net/fabricmc/loom/test/integration/forge/LegacyAw2AtTest.groovy50
-rw-r--r--src/test/resources/projects/forge/aw2At/build.gradle89
-rw-r--r--src/test/resources/projects/forge/aw2At/expected.accesstransformer.cfg2
-rw-r--r--src/test/resources/projects/forge/aw2At/gradle.properties17
-rw-r--r--src/test/resources/projects/forge/aw2At/settings.gradle2
-rw-r--r--src/test/resources/projects/forge/aw2At/src/main/resources/my.accesswidener3
-rw-r--r--src/test/resources/projects/forge/legacyAw2At/build.gradle89
-rw-r--r--src/test/resources/projects/forge/legacyAw2At/expected.accesstransformer.cfg2
-rw-r--r--src/test/resources/projects/forge/legacyAw2At/gradle.properties17
-rw-r--r--src/test/resources/projects/forge/legacyAw2At/settings.gradle2
-rw-r--r--src/test/resources/projects/forge/legacyAw2At/src/main/resources/my.accesswidener3
30 files changed, 779 insertions, 29 deletions
diff --git a/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java b/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
index f8ed71d3..5242d624 100644
--- a/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
+++ b/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
@@ -35,7 +35,6 @@ import org.gradle.api.plugins.PluginAware;
import org.jetbrains.annotations.NotNull;
import net.fabricmc.loom.extension.LoomFiles;
-
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.MirrorUtil;
diff --git a/src/main/java/net/fabricmc/loom/api/ForgeExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/ForgeExtensionAPI.java
new file mode 100644
index 00000000..7cfc639c
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/api/ForgeExtensionAPI.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.SetProperty;
+
+/**
+ * This is the forge extension api available exposed to build scripts.
+ */
+// TODO: Move other forge-related configuration here
+public interface ForgeExtensionAPI {
+ /**
+ * If true, {@linkplain LoomGradleExtensionAPI#getAccessWidenerPath() the project access widener file}
+ * will be remapped to an access transformer file if set.
+ *
+ * @return the property
+ */
+ Property<Boolean> getConvertAccessWideners();
+
+ /**
+ * A set of additional access widener files that will be converted to access transformers
+ * {@linkplain #getConvertAccessWideners() if enabled}. The files are specified as paths in jar files
+ * (e.g. {@code path/to/my_aw.accesswidener}).
+ *
+ * @return the property
+ */
+ SetProperty<String> getExtraAccessWideners();
+}
diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
index ab5db4a8..ee11b0ad 100644
--- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
+++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
@@ -248,4 +248,16 @@ public interface LoomGradleExtensionAPI {
void setUseFabricMixin(boolean useFabricMixin);
List<Consumer<RunConfig>> getSettingsPostEdit();
+
+ /**
+ * Gets the Forge extension used to configure Forge details.
+ * Note that (for now) some Forge configuration is instead in this interface -
+ * this is due to change in the future.
+ *
+ * @return the Forge extension
+ * @throws UnsupportedOperationException if running on another platform
+ */
+ ForgeExtensionAPI getForge();
+
+ void forge(Action<ForgeExtensionAPI> action);
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
index 8a6c367e..ae392d00 100644
--- a/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
+++ b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
@@ -33,6 +33,7 @@ import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException;
import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.provider.Property;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.bundling.Jar;
import org.jetbrains.annotations.ApiStatus;
@@ -45,6 +46,7 @@ import net.fabricmc.loom.task.RemapAllSourcesTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.util.SourceRemapper;
+import net.fabricmc.loom.util.aw2at.Aw2At;
public class RemapConfiguration {
private static final String DEFAULT_JAR_TASK_NAME = JavaPlugin.JAR_TASK_NAME;
@@ -89,6 +91,16 @@ public class RemapConfiguration {
remapJarTask.getRemapAccessWidener().set(true);
project.getArtifacts().add("archives", remapJarTask);
+
+ if (extension.isForge()) {
+ Property<Boolean> convertAws = extension.getForge().getConvertAccessWideners();
+ convertAws.finalizeValue();
+
+ if (convertAws.get()) {
+ Aw2At.setup(project, remapJarTask);
+ remapJarTask.getRemapAccessWidener().set(false);
+ }
+ }
}
remapJarTask.dependsOn(jarTask);
diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
index c7c0792f..5bc30591 100644
--- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
+++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java
@@ -280,7 +280,7 @@ public final class RunConfigSettings implements Named {
public void client() {
startFirstThread();
environment("client");
- defaultMainClass(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : Constants.Knot.KNOT_CLIENT);
+ defaultMainClass(getExtension().isForge() ? Constants.Forge.LAUNCH_TESTING : Constants.Knot.KNOT_CLIENT);
}
/**
@@ -289,7 +289,7 @@ public final class RunConfigSettings implements Named {
public void server() {
programArg("nogui");
environment("server");
- defaultMainClass(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : Constants.Knot.KNOT_SERVER);
+ defaultMainClass(getExtension().isForge() ? Constants.Forge.LAUNCH_TESTING : Constants.Knot.KNOT_SERVER);
}
/**
@@ -297,7 +297,7 @@ public final class RunConfigSettings implements Named {
*/
public void data() {
environment("data");
- defaultMainClass(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : Constants.Knot.KNOT_SERVER);
+ defaultMainClass(getExtension().isForge() ? Constants.Forge.LAUNCH_TESTING : Constants.Knot.KNOT_SERVER);
}
/**
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
index 73b6f827..c339ae2e 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
@@ -152,7 +152,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
SourceSet main = getProject().getConvention().findPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
for (File srcDir : main.getResources().getSrcDirs()) {
- File projectAt = new File(srcDir, "META-INF/accesstransformer.cfg");
+ File projectAt = new File(srcDir, Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (projectAt.exists()) {
this.projectAts.add(projectAt);
@@ -373,8 +373,8 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
}
- private static void visitMojmap(MappingVisitor visitor, LoomGradleExtension extension) {
- GradleMappingContext context = new GradleMappingContext(extension.getForgeProvider().getProject(), "tmp-mojmap");
+ private static void visitMojmap(MappingVisitor visitor, Project project) {
+ GradleMappingContext context = new GradleMappingContext(project, "tmp-mojmap");
try {
FileUtils.deleteDirectory(context.workingDirectory("/"));
@@ -391,12 +391,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
}
- public static Path getMojmapTsrg(LoomGradleExtension extension) throws IOException {
+ public static Path getMojmapTsrg(Project project, LoomGradleExtension extension) throws IOException {
Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg");
if (Files.notExists(path)) {
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
- Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, extension),
+ Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, project),
MappingNamespace.NAMED.stringValue(), false, writer);
}
}
@@ -404,12 +404,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
return path;
}
- public static Path getMojmapTsrg2(LoomGradleExtension extension) throws IOException {
+ public static Path getMojmapTsrg2(Project project, LoomGradleExtension extension) throws IOException {
Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg2");
if (Files.notExists(path)) {
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
- Tsrg2Utils.writeTsrg2(visitor -> visitMojmap(visitor, extension), writer);
+ Tsrg2Utils.writeTsrg2(visitor -> visitMojmap(visitor, project), writer);
}
}
@@ -426,7 +426,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
"--left",
getExtension().getMcpConfigProvider().getMappings().toAbsolutePath().toString(),
"--right",
- getMojmapTsrg(getExtension()).toAbsolutePath().toString(),
+ getMojmapTsrg(getProject(), getExtension()).toAbsolutePath().toString(),
"--classes",
"--output",
out.toAbsolutePath().toString()
@@ -585,7 +585,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
for (File jar : ImmutableList.of(getForgeJar(), getForgeUserdevJar(), minecraftMergedPatchedSrgJar)) {
try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(jar, false)) {
- Path atPath = fs.get().getPath("META-INF/accesstransformer.cfg");
+ Path atPath = fs.get().getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (Files.exists(atPath)) {
File tmpFile = File.createTempFile("at-conf", ".cfg");
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
index eb6343cc..519c82a5 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
@@ -116,6 +116,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
if (getExtension().shouldGenerateSrgTiny()) {
return MappingsCache.INSTANCE.get(tinyMappingsWithSrg);
}
+
throw new UnsupportedOperationException("Not running with Forge support / Tiny srg support.");
}
@@ -230,7 +231,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
protected Path getMojmapSrgFileIfPossible() {
try {
LoomGradleExtension extension = getExtension();
- return MinecraftPatchedProvider.getMojmapTsrg2(extension);
+ return MinecraftPatchedProvider.getMojmapTsrg2(getProject(), extension);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -453,7 +454,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
"intermediary", "official");
} catch (Exception e) {
throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString()
- + " with mappings from " + yarnMappings, e);
+ + " with mappings from " + yarnMappings, e);
}
}
diff --git a/src/main/java/net/fabricmc/loom/extension/ForgeExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/ForgeExtensionImpl.java
new file mode 100644
index 00000000..6794b651
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/extension/ForgeExtensionImpl.java
@@ -0,0 +1,54 @@
+/*
+ * 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.extension;
+
+import javax.inject.Inject;
+
+import org.gradle.api.Project;
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.SetProperty;
+
+import net.fabricmc.loom.api.ForgeExtensionAPI;
+
+public class ForgeExtensionImpl implements ForgeExtensionAPI {
+ private final Property<Boolean> convertAccessWideners;
+ private final SetProperty<String> extraAccessWideners;
+
+ @Inject
+ public ForgeExtensionImpl(Project project) {
+ convertAccessWideners = project.getObjects().property(Boolean.class).convention(false);
+ extraAccessWideners = project.getObjects().setProperty(String.class).empty();
+ }
+
+ @Override
+ public Property<Boolean> getConvertAccessWideners() {
+ return convertAccessWideners;
+ }
+
+ @Override
+ public SetProperty<String> getExtraAccessWideners() {
+ return extraAccessWideners;
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
index 1f274f12..d5cdada0 100644
--- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
@@ -43,11 +43,12 @@ import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
-import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
+import net.fabricmc.loom.api.ForgeExtensionAPI;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinApExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
@@ -257,10 +258,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
@SuppressWarnings("Convert2Lambda")
@Override
public void localMods(Action<SourceSetConsumer> action) {
- if (!isForge()) {
- throw new UnsupportedOperationException("Not running with Forge support.");
- }
-
+ ModPlatform.assertPlatform(this, ModPlatform.FORGE);
action.execute(new SourceSetConsumer() {
@Override
public void add(Object... sourceSets) {
@@ -283,10 +281,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
@SuppressWarnings("Convert2Lambda")
@Override
public void dataGen(Action<DataGenConsumer> action) {
- if (!isForge()) {
- throw new UnsupportedOperationException("Not running with Forge support.");
- }
-
+ ModPlatform.assertPlatform(this, ModPlatform.FORGE);
action.execute(new DataGenConsumer() {
@Override
public void mod(String... modIds) {
@@ -339,6 +334,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
return settingsPostEdit;
}
+ @Override
+ public void forge(Action<ForgeExtensionAPI> action) {
+ action.execute(getForge());
+ }
+
// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
private final class EnsureCompile extends LoomGradleExtensionApiImpl {
private EnsureCompile() {
@@ -380,5 +380,10 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected String getMinecraftVersion() {
throw new RuntimeException("Yeah... something is really wrong");
}
+
+ @Override
+ public ForgeExtensionAPI getForge() {
+ throw new RuntimeException("Yeah... something is really wrong");
+ }
}
}
diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
index 730d683b..172944cc 100644
--- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
@@ -33,6 +33,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
+import com.google.common.base.Suppliers;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.NamedDomainObjectProvider;
@@ -41,15 +42,18 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
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.processors.JarProcessorManager;
+import net.fabricmc.loom.util.ModPlatform;
public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension {
private final Project project;
private final MixinApExtension mixinApExtension;
private final LoomFiles loomFiles;
private final ConfigurableFileCollection unmappedMods;
+ private final Supplier<ForgeExtensionAPI> forgeExtension;
private final Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>());
private final MappingSet[] srcMappingCache = new MappingSet[2];
@@ -67,6 +71,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
this.mixinApExtension = project.getObjects().newInstance(MixinApExtensionImpl.class, project);
this.loomFiles = files;
this.unmappedMods = project.files();
+ this.forgeExtension = Suppliers.memoize(() -> isForge() ? project.getObjects().newInstance(ForgeExtensionImpl.class, project) : null);
}
@Override
@@ -175,4 +180,10 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
protected String getMinecraftVersion() {
return getMinecraftProvider().minecraftVersion();
}
+
+ @Override
+ public ForgeExtensionAPI getForge() {
+ ModPlatform.assertPlatform(this, ModPlatform.FORGE);
+ return forgeExtension.get();
+ }
}
diff --git a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
index 5550cb8a..b9df337e 100644
--- a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
+++ b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
@@ -39,6 +39,7 @@ import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
+import net.fabricmc.loom.api.ForgeExtensionAPI;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinApExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
@@ -273,4 +274,16 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
reportDeprecation();
return parent.getSettingsPostEdit();
}
+
+ @Override
+ public ForgeExtensionAPI getForge() {
+ reportDeprecation();
+ return parent.getForge();
+ }
+
+ @Override
+ public void forge(Action<ForgeExtensionAPI> action) {
+ reportDeprecation();
+ parent.forge(action);
+ }
}
diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
index f202b7f7..f29f773a 100644
--- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
+++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
@@ -30,11 +30,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
+import java.io.Writer;
import java.net.URI;
import java.nio.charset.StandardCharsets;
+import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.AbstractMap;
import java.util.ArrayList;
@@ -61,12 +64,15 @@ import dev.architectury.refmapremapper.remapper.SimpleReferenceRemapper;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.TinyRemapper;
import dev.architectury.tinyremapper.TinyUtils;
+import org.cadixdev.at.AccessTransformSet;
+import org.cadixdev.at.io.AccessTransformFormats;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
+import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.TaskAction;
@@ -90,9 +96,12 @@ import net.fabricmc.loom.configuration.JarManifestConfiguration;
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.ZipReprocessorUtil;
+import net.fabricmc.loom.util.aw2at.Aw2At;
+import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef;
@@ -109,6 +118,7 @@ public class RemapJarTask extends Jar {
private final List<Action<TinyRemapper.Builder>> remapOptions = new ArrayList<>();
private final Property<String> fromM;
private final Property<String> toM;
+ private final SetProperty<String> atAccessWideners;
public JarRemapper jarRemapper;
private FileCollection classpath;
private final Set<Object> nestedPaths = new LinkedHashSet<>();
@@ -121,6 +131,7 @@ public class RemapJarTask extends Jar {
remapAccessWidener = getProject().getObjects().property(Boolean.class);
fromM = getProject().getObjects().property(String.class);
toM = getProject().getObjects().property(String.class);
+ atAccessWideners = getProject().getObjects().setProperty(String.class).empty();
fromM.set("named");
toM.set(SourceRemapper.intermediary(getProject()));
// false by default, I have no idea why I have to do it for this property and not the other one
@@ -142,6 +153,8 @@ public class RemapJarTask extends Jar {
if (singleRemap) {
jarRemapper.remap(getProject());
}
+
+ convertAwToAt();
}
private ReferenceRemapper createReferenceRemapper(LoomGradleExtension extension, String from, String to) throws IOException {
@@ -442,6 +455,53 @@ public class RemapJarTask extends Jar {
.toArray(Path[]::new);
}
+ private void convertAwToAt() throws IOException {
+ if (!this.atAccessWideners.isPresent()) {
+ return;
+ }
+
+ Set<String> atAccessWideners = this.atAccessWideners.get();
+
+ if (atAccessWideners.isEmpty()) {
+ return;
+ }
+
+ AccessTransformSet at = AccessTransformSet.create();
+ File jar = getArchiveFile().get().getAsFile();
+
+ try (FileSystemUtil.FileSystemDelegate fileSystem = FileSystemUtil.getJarFileSystem(jar, false)) {
+ FileSystem fs = fileSystem.get();
+ Path atPath = fs.getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH);
+
+ if (Files.exists(atPath)) {
+ throw new FileAlreadyExistsException("Jar " + jar + " already contains an access transformer - cannot convert AWs!");
+ }
+
+ for (String aw : atAccessWideners) {
+ Path awPath = fs.getPath(aw);
+
+ if (Files.notExists(awPath)) {
+ throw new NoSuchFileException("Could not find AW '" + aw + "' to convert into AT!");
+ }
+
+ try (InputStream in = Files.newInputStream(awPath)) {
+ at.merge(Aw2At.toAccessTransformSet(in));
+ }
+
+ Files.delete(awPath);
+ }
+
+ LoomGradleExtension extension = LoomGradleExtension.get(getProject());
+ TinyTree mappings = extension.shouldGenerateSrgTiny() ? extension.getMappingsProvider().getMappingsWithSrg() : extension.getMappingsProvider().getMappings();
+ TinyMappingsReader reader = new TinyMappingsReader(mappings, fromM.get(), toM.get());
+ at = at.remap(reader.read());
+
+ try (Writer writer = Files.newBufferedWriter(atPath)) {
+ AccessTransformFormats.FML.write(writer, at);
+ }
+ }
+ }
+
@InputFile
public RegularFileProperty getInput() {
return input;
@@ -462,6 +522,19 @@ public class RemapJarTask extends Jar {
return remapAccessWidener;
}
+ /**
+ * Gets the jar paths to the access wideners that will be converted to ATs for Forge runtime.
+ * If you specify multiple files, they will be merged into one.
+ *
+ * <p>The specified files will be converted and removed from the final jar.
+ *
+ * @return the property containing access widener paths in the final jar
+ */
+ @Input
+ public SetProperty<String> getAtAccessWideners() {
+ return atAccessWideners;
+ }
+
public void remapOptions(Action<TinyRemapper.Builder> action) {
this.remapOptions.add(action);
}
diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java
index f3f0bf5a..936f61ae 100644
--- a/src/main/java/net/fabricmc/loom/util/Constants.java
+++ b/src/main/java/net/fabricmc/loom/util/Constants.java
@@ -149,10 +149,11 @@ public class Constants {
}
}
- public static final class ForgeUserDev {
+ public static final class Forge {
public static final String LAUNCH_TESTING = "net.minecraftforge.userdev.LaunchTesting";
+ public static final String ACCESS_TRANSFORMER_PATH = "META-INF/accesstransformer.cfg";
- private ForgeUserDev() {
+ private Forge() {
}
}
}
diff --git a/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java b/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java
index 6bdb7932..7a8bd7f1 100644
--- a/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java
+++ b/src/main/java/net/fabricmc/loom/util/MappingsProviderVerbose.java
@@ -1,8 +1,31 @@
+/*
+ * 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.IOException;
import java.lang.reflect.Field;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
diff --git a/src/main/java/net/fabricmc/loom/util/ModPlatform.java b/src/main/java/net/fabricmc/loom/util/ModPlatform.java
index ee8275a0..e10e93d3 100644
--- a/src/main/java/net/fabricmc/loom/util/ModPlatform.java
+++ b/src/main/java/net/fabricmc/loom/util/ModPlatform.java
@@ -24,7 +24,29 @@
package net.fabricmc.loom.util;
+import java.util.Locale;
+
+import org.gradle.api.GradleException;
+import org.gradle.api.Project;
+
+import net.fabricmc.loom.LoomGradleExtension;
+import net.fabricmc.loom.api.LoomGradleExtensionAPI;
+
public enum ModPlatform {
FABRIC,
- FORGE,
+ FORGE;
+
+ public static void assertPlatform(Project project, ModPlatform platform) {
+ assertPlatform(LoomGradleExtension.get(project), platform);
+ }
+
+ public static void assertPlatform(LoomGradleExtensionAPI extension, ModPlatform platform) {
+ extension.getPlatform().finalizeValue();
+
+ if (extension.getPlatform().get() != platform) {
+ String msg = "Loom is not running on %s.%nYou can switch to it by adding 'loom.platform = %s' to your gradle.properties";
+ String name = platform.name().toLowerCase(Locale.ROOT);
+ throw new GradleException(String.format(msg, name, name));
+ }
+ }
}
diff --git a/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java b/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java
new file mode 100644
index 00000000..8c9dbe08
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java
@@ -0,0 +1,122 @@
+/*
+ * 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.aw2at;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+
+import org.cadixdev.at.AccessChange;
+import org.cadixdev.at.AccessTransform;
+import org.cadixdev.at.AccessTransformSet;
+import org.cadixdev.at.ModifierChange;
+import org.cadixdev.bombe.type.signature.MethodSignature;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+
+import net.fabricmc.accesswidener.AccessWidenerReader;
+import net.fabricmc.loom.LoomGradleExtension;
+import net.fabricmc.loom.task.RemapJarTask;
+
+/**
+ * Converts AW files to AT files.
+ *
+ * @author Juuz
+ */
+public final class Aw2At {
+ public static void setup(Project project, RemapJarTask remapJar) {
+ LoomGradleExtension extension = LoomGradleExtension.get(project);
+
+ if (extension.getAccessWidenerPath().isPresent()) {
+ // Find the relative AW file name
+ String awName = null;
+ Path awPath = extension.getAccessWidenerPath().get().getAsFile().toPath();
+ SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
+ SourceSet main = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
+ boolean found = false;
+
+ for (File srcDir : main.getResources().getSrcDirs()) {
+ Path srcDirPath = srcDir.toPath().toAbsolutePath();
+
+ if (awPath.startsWith(srcDirPath)) {
+ awName = srcDirPath.relativize(awPath).toString().replace(File.separator, "/");
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ awName = awPath.getFileName().toString();
+ }
+
+ remapJar.getAtAccessWideners().add(awName);
+ }
+
+ remapJar.getAtAccessWideners().addAll(extension.getForge().getExtraAccessWideners());
+ }
+
+ public static AccessTransformSet toAccessTransformSet(InputStream in) throws IOException {
+ AccessTransformSet atSet = AccessTransformSet.create();
+
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
+ new AccessWidenerReader(new AccessWidenerReader.Visitor() {
+ @Override
+ public void visitClass(String name, AccessWidenerReader.AccessType access) {
+ atSet.getOrCreateClass(name).merge(toAt(access));
+ }
+
+ @Override
+ public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access) {
+ atSet.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), toAt(access));
+ }
+
+ @Override
+ public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access) {
+ atSet.getOrCreateClass(owner).mergeField(name, toAt(access));
+ }
+ }).read(reader);
+ }
+
+ return atSet;
+ }
+
+ private static AccessTransform toAt(AccessWidenerReader.AccessType access) {
+ return switch (access) {
+ // FIXME: This behaviour doesn't match what the actual AW does for methods.
+ // - accessible makes the method final if it was private
+ // - extendable makes the method protected if it was (package-)private
+ // Neither of these can be achieved with Forge ATs without using bytecode analysis.
+ // However, this might be good enough for us. (The effects only apply in prod.)
+ case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC);
+ case EXTENDABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE);
+ case MUTABLE -> AccessTransform.of(ModifierChange.REMOVE);
+ };
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java
index eadeecaa..c435498a 100644
--- a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java
+++ b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java
@@ -40,6 +40,7 @@ import java.util.function.UnaryOperator;
import com.google.common.collect.ImmutableMap;
import org.gradle.api.logging.Logger;
+import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
@@ -51,7 +52,7 @@ import net.fabricmc.mapping.tree.TinyTree;
public final class AtRemapper {
public static void remap(Logger logger, Path jar, TinyTree mappings) throws IOException {
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + jar.toUri()), ImmutableMap.of("create", false))) {
- Path atPath = fs.getPath("META-INF/accesstransformer.cfg");
+ Path atPath = fs.getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (Files.exists(atPath)) {
String atContent = Files.readString(atPath);
diff --git a/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java b/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java
index e6ddf578..6279d569 100644
--- a/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java
+++ b/src/main/java/net/fabricmc/loom/util/srg/Tsrg2Utils.java
@@ -1,3 +1,27 @@
+/*
+ * 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.srg;
import java.io.IOException;
diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Aw2AtTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Aw2AtTest.groovy
new file mode 100644
index 00000000..fc7c016d
--- /dev/null
+++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Aw2AtTest.groovy
@@ -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.test.integration.forge
+
+import net.fabricmc.loom.test.util.ArchiveAssertionsTrait
+import net.fabricmc.loom.test.util.ProjectTestTrait
+import spock.lang.Specification
+
+import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
+
+class Aw2AtTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait {
+ @Override
+ String name() {
+ "forge/aw2At"
+ }
+
+ def build() {
+ when:
+ def result = create("build", DEFAULT_GRADLE)
+ then:
+ result.task(":build").outcome == SUCCESS
+ getArchiveEntry("fabric-example-mod-1.0.0.jar", "META-INF/accesstransformer.cfg") == expected().replaceAll('\r', '')
+ }
+
+ String expected() {
+ return new File(testProjectDir, "expected.accesstransformer.cfg").text
+ }
+}
diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/LegacyAw2AtTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/LegacyAw2AtTest.groovy
new file mode 100644
index 00000000..bdd9a5aa
--- /dev/null
+++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/LegacyAw2AtTest.groovy
@@ -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.test.integration.forge
+
+import net.fabricmc.loom.test.util.ArchiveAssertionsTrait
+import net.fabricmc.loom.test.util.ProjectTestTrait
+import spock.lang.Specification
+
+import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
+
+class LegacyAw2AtTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait {
+ @Override
+ String name() {
+ "forge/legacyAw2At"
+ }
+
+ def build() {
+ when:
+ def result = create("build", DEFAULT_GRADLE)
+ then:
+ result.task(":build").outcome == SUCCESS
+ getArchiveEntry("fabric-example-mod-1.0.0.jar", "META-INF/accesstransformer.cfg") == expected().replaceAll('\r', '')
+ }
+
+ String expected() {
+ return new File(testProjectDir, "expected.accesstransformer.cfg").text
+ }
+}
diff --git a/src/test/resources/projects/forge/aw2At/build.gradle b/src/test/resources/projects/forge/aw2At/build.gradle
new file mode 100644
index 00000000..81ff4b9b
--- /dev/null
+++ b/src/test/resources/projects/forge/aw2At/build.gradle
@@ -0,0 +1,89 @@
+plugins {
+ id 'dev.architectury.loom'
+ id 'maven-publish'
+}
+
+sourceCompatibility = JavaVersion.VERSION_1_8
+targetCompatibility = JavaVersion.VERSION_1_8
+
+archivesBaseName = project.archives_base_name
+version = project.mod_version
+group = project.maven_group
+
+def mcVersion = '1.17.1'
+def forgeVersion = '37.0.13'
+
+loom {
+ accessWidenerPath = file('src/main/resources/my.accesswidener')
+
+ forge {
+ convertAccessWideners = true
+ }
+}
+
+repositories {
+ // Add repositories to retrieve artifacts from in here.
+ // You should only use this when depending on other mods because
+ // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
+ // See https://docs.gradle.org/current/userguide/declaring_repositories.html
+ // for more information about repositories.
+}
+
+dependencies {
+ // To change the versions see the gradle.properties file
+ minecraft "com.mojang:minecraft:$mcVersion"
+ mappings loom.officialMojangMappings()
+ forge "net.minecraftforge:forge:$mcVersion-$forgeVersion"
+}
+
+tasks.withType(JavaCompile).configureEach {
+ // ensure that the encoding is set to UTF-8, no matter what the system default is
+ // this fixes some edge cases with special characters not displaying correctly
+ // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
+ // If Javadoc is generated, this must be specified in that task too.
+ it.options.encoding = "UTF-8"
+
+ // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
+ // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
+ // We'll use that if it's available, but otherwise we'll use the older option.
+ def targetVersion = 8
+ if (JavaVersion.current().isJava9Compatible()) {
+ it.options.release = targetVersion
+ }
+}
+
+java {
+ // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
+ // if it is present.
+ // If you remove this line, sources will not be generated.
+ withSourcesJar()
+}
+
+jar {
+ from("LICENSE") {
+ rename { "${it}_${project.archivesBaseName}"}
+ }
+}
+
+// configure the maven publication
+publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ // add all the jars that should be included when publishing to maven
+ artifact(remapJar) {
+ builtBy remapJar
+ }
+ artifact(sourcesJar) {
+ builtBy remapSourcesJar
+ }
+ }
+ }
+
+ // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
+ repositories {
+ // Add repositories to publish to here.
+ // Notice: This block does NOT have the same function as the block in the top level.
+ // The repositories here will be used for publishing your artifact, not for
+ // retrieving dependencies.
+ }
+}
diff --git a/src/test/resources/projects/forge/aw2At/expected.accesstransformer.cfg b/src/test/resources/projects/forge/aw2At/expected.accesstransformer.cfg
new file mode 100644
index 00000000..493714c9
--- /dev/null
+++ b/src/test/resources/projects/forge/aw2At/expected.accesstransformer.cfg
@@ -0,0 +1,2 @@
+public net.minecraft.world.level.GameRules$BooleanValue m_46250_(Z)Lnet/minecraft/world/level/GameRules$Type;
+public-f net.minecraft.world.level.block.IronBarsBlock m_54217_(Lnet/minecraft/world/level/block/state/BlockState;Z)Z
diff --git a/src/test/resources/projects/forge/aw2At/gradle.properties b/src/test/resources/projects/forge/aw2At/gradle.properties
new file mode 100644
index 00000000..f3b2ac32
--- /dev/null
+++ b/src/test/resources/projects/forge/aw2At/gradle.properties
@@ -0,0 +1,17 @@
+# Done to increase the memory available to gradle.
+org.gradle.jvmargs=-Xmx1G
+
+# Fabric Properties
+# check these on https://fabricmc.net/use
+loader_version=0.11.2
+
+# Mod Properties
+mod_version = 1.0.0
+maven_group = com.example
+archives_base_name = fabric-example-mod
+
+# Dependencies
+# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
+fabric_version=0.31.0+1.16
+
+loom.platform=forge
diff --git a/src/test/resources/projects/forge/aw2At/settings.gradle b/src/test/resources/projects/forge/aw2At/settings.gradle
new file mode 100644
index 00000000..c162c363
--- /dev/null
+++ b/src/test/resources/projects/forge/aw2At/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "fabric-example-mod"
+
diff --git a/src/test/resources/projects/forge/aw2At/src/main/resources/my.accesswidener b/src/test/resources/projects/forge/aw2At/src/main/resources/my.accesswidener
new file mode 100644
index 00000000..2f88fa59
--- /dev/null
+++ b/src/test/resources/projects/forge/aw2At/src/main/resources/my.accesswidener
@@ -0,0 +1,3 @@
+accessWidener v1 named
+accessible method net/minecraft/world/level/GameRules$BooleanValue create (Z)Lnet/minecraft/world/GameRules$Type;
+extendable method net/minecraft/world/level/block/IronBarsBlock attchsTo (Lnet/minecraft/world/level/block/state/BlockState;Z)Z
diff --git a/src/test/resources/projects/forge/legacyAw2At/build.gradle b/src/test/resources/projects/forge/legacyAw2At/build.gradle
new file mode 100644
index 00000000..1b319a1b
--- /dev/null
+++ b/src/test/resources/projects/forge/legacyAw2At/build.gradle
@@ -0,0 +1,89 @@
+plugins {
+ id 'dev.architectury.loom'
+ id 'maven-publish'
+}
+
+sourceCompatibility = JavaVersion.VERSION_1_8
+targetCompatibility = JavaVersion.VERSION_1_8
+
+archivesBaseName = project.archives_base_name
+version = project.mod_version
+group = project.maven_group
+
+def mcVersion = '1.16.5'
+def forgeVersion = '36.2.2'
+
+loom {
+ accessWidenerPath = file('src/main/resources/my.accesswidener')
+
+ forge {
+ convertAccessWideners = true
+ }
+}
+
+repositories {
+ // Add repositories to retrieve artifacts from in here.
+ // You should only use this when depending on other mods because
+ // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
+ // See https://docs.gradle.org/current/userguide/declaring_repositories.html
+ // for more information about repositories.
+}
+
+dependencies {
+ // To change the versions see the gradle.properties file
+ minecraft "com.mojang:minecraft:$mcVersion"
+ mappings loom.officialMojangMappings()
+ forge "net.minecraftforge:forge:$mcVersion-$forgeVersion"
+}
+
+tasks.withType(JavaCompile).configureEach {
+ // ensure that the encoding is set to UTF-8, no matter what the system default is
+ // this fixes some edge cases with special characters not displaying correctly
+ // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
+ // If Javadoc is generated, this must be specified in that task too.
+ it.options.encoding = "UTF-8"
+
+ // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
+ // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
+ // We'll use that if it's available, but otherwise we'll use the older option.
+ def targetVersion = 8
+ if (JavaVersion.current().isJava9Compatible()) {
+ it.options.release = targetVersion
+ }
+}
+
+java {
+ // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
+ // if it is present.
+ // If you remove this line, sources will not be generated.
+ withSourcesJar()
+}
+
+jar {
+ from("LICENSE") {
+ rename { "${it}_${project.archivesBaseName}"}
+ }
+}
+
+// configure the maven publication
+publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ // add all the jars that should be included when publishing to maven
+ artifact(remapJar) {
+ builtBy remapJar
+ }
+ artifact(sourcesJar) {
+ builtBy remapSourcesJar
+ }
+ }
+ }
+
+ // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
+ repositories {
+ // Add repositories to publish to here.
+ // Notice: This block does NOT have the same function as the block in the top level.
+ // The repositories here will be used for publishing your artifact, not for
+ // retrieving dependencies.
+ }
+}
diff --git a/src/test/resources/projects/forge/legacyAw2At/expected.accesstransformer.cfg b/src/test/resources/projects/forge/legacyAw2At/expected.accesstransformer.cfg
new file mode 100644
index 00000000..f04789ab
--- /dev/null
+++ b/src/test/resources/projects/forge/legacyAw2At/expected.accesstransformer.cfg
@@ -0,0 +1,2 @@
+public net.minecraft.world.GameRules$BooleanValue func_223568_b(Z)Lnet/minecraft/world/GameRules$RuleType;
+public-f net.minecraft.block.PaneBlock func_220112_a(Lnet/minecraft/block/BlockState;Z)Z
diff --git a/src/test/resources/projects/forge/legacyAw2At/gradle.properties b/src/test/resources/projects/forge/legacyAw2At/gradle.properties
new file mode 100644
index 00000000..f3b2ac32
--- /dev/null
+++ b/src/test/resources/projects/forge/legacyAw2At/gradle.properties
@@ -0,0 +1,17 @@
+# Done to increase the memory available to gradle.
+org.gradle.jvmargs=-Xmx1G
+
+# Fabric Properties
+# check these on https://fabricmc.net/use
+loader_version=0.11.2
+
+# Mod Properties
+mod_version = 1.0.0
+maven_group = com.example
+archives_base_name = fabric-example-mod
+
+# Dependencies
+# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
+fabric_version=0.31.0+1.16
+
+loom.platform=forge
diff --git a/src/test/resources/projects/forge/legacyAw2At/settings.gradle b/src/test/resources/projects/forge/legacyAw2At/settings.gradle
new file mode 100644
index 00000000..c162c363
--- /dev/null
+++ b/src/test/resources/projects/forge/legacyAw2At/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "fabric-example-mod"
+
diff --git a/src/test/resources/projects/forge/legacyAw2At/src/main/resources/my.accesswidener b/src/test/resources/projects/forge/legacyAw2At/src/main/resources/my.accesswidener
new file mode 100644
index 00000000..2f88fa59
--- /dev/null
+++ b/src/test/resources/projects/forge/legacyAw2At/src/main/resources/my.accesswidener
@@ -0,0 +1,3 @@
+accessWidener v1 named
+accessible method net/minecraft/world/level/GameRules$BooleanValue create (Z)Lnet/minecraft/world/GameRules$Type;
+extendable method net/minecraft/world/level/block/IronBarsBlock attchsTo (Lnet/minecraft/world/level/block/state/BlockState;Z)Z