aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/net/fabricmc/loom
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/fabricmc/loom')
-rw-r--r--src/main/java/net/fabricmc/loom/LoomGradleExtension.java8
-rw-r--r--src/main/java/net/fabricmc/loom/LoomGradlePlugin.java8
-rw-r--r--src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java116
-rw-r--r--src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java6
-rw-r--r--src/main/java/net/fabricmc/loom/build/JarRemapper.java43
-rw-r--r--src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java101
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java4
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java2
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java4
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java2
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java11
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java11
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java5
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java14
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java9
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java12
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java61
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java10
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java32
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java4
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java13
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java2
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java8
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java7
-rw-r--r--src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java1
-rw-r--r--src/main/java/net/fabricmc/loom/decompilers/DecompilerConfiguration.java4
-rw-r--r--src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java115
-rw-r--r--src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java5
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java134
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MixinApExtension.java39
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MixinApExtensionApiImpl.java47
-rw-r--r--src/main/java/net/fabricmc/loom/extension/MixinApExtensionImpl.java39
-rw-r--r--src/main/java/net/fabricmc/loom/task/AbstractRunTask.java2
-rw-r--r--src/main/java/net/fabricmc/loom/task/LoomTasks.java14
-rw-r--r--src/main/java/net/fabricmc/loom/task/RemapAllSourcesTask.java12
-rw-r--r--src/main/java/net/fabricmc/loom/task/RemapJarTask.java2
-rw-r--r--src/main/java/net/fabricmc/loom/util/CloseableList.java52
-rw-r--r--src/main/java/net/fabricmc/loom/util/Constants.java9
-rw-r--r--src/main/java/net/fabricmc/loom/util/DeprecationHelper.java86
-rw-r--r--src/main/java/net/fabricmc/loom/util/SourceRemapper.java283
40 files changed, 969 insertions, 368 deletions
diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
index 71ce957e..6c3541e9 100644
--- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
+++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java
@@ -50,12 +50,11 @@ import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.extension.LoomFiles;
-import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
import net.fabricmc.loom.extension.MixinApExtension;
public interface LoomGradleExtension extends LoomGradleExtensionAPI {
static LoomGradleExtension get(Project project) {
- return project.getExtensions().getByType(LoomGradleExtensionImpl.class);
+ return (LoomGradleExtension) project.getExtensions().getByName("loom");
}
LoomFiles getFiles();
@@ -100,8 +99,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
boolean isRootProject();
- boolean isShareCaches();
-
default boolean ideSync() {
return Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"));
}
@@ -111,7 +108,8 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
return String.format("https://maven.fabricmc.net/net/fabricmc/intermediary/%1$s/intermediary-%1$s-v2.jar", minecraftVersion);
}
- MixinApExtension getMixinApExtension();
+ @Override
+ MixinApExtension getMixin();
// ===================
// Architectury Loom
diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java
index a79c5a8d..8cd9cb5a 100644
--- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java
+++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java
@@ -38,6 +38,7 @@ import com.google.gson.GsonBuilder;
import org.gradle.api.Project;
import org.gradle.api.plugins.PluginAware;
+import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.bootstrap.BootstrappedPlugin;
import net.fabricmc.loom.configuration.CompileConfiguration;
import net.fabricmc.loom.configuration.FabricApiExtension;
@@ -47,6 +48,7 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
import net.fabricmc.loom.extension.LoomFilesImpl;
+import net.fabricmc.loom.extension.MinecraftGradleExtension;
import net.fabricmc.loom.task.LoomTasks;
public class LoomGradlePlugin implements BootstrappedPlugin {
@@ -86,9 +88,9 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea"));
- // Setup extensions, loom shadows minecraft
- project.getExtensions().create(LoomGradleExtension.class, "minecraft", LoomGradleExtensionImpl.class, project, new LoomFilesImpl(project));
- project.getExtensions().add("loom", project.getExtensions().getByName("minecraft"));
+ // Setup extensions, minecraft wraps loom
+ var extension = project.getExtensions().create(LoomGradleExtensionAPI.class, "loom", LoomGradleExtensionImpl.class, project, new LoomFilesImpl(project));
+ project.getExtensions().create(LoomGradleExtensionAPI.class, "minecraft", MinecraftGradleExtension.class, extension);
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);
CompileConfiguration.setupConfigurations(project);
diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
index 146be30d..5230f9b9 100644
--- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
+++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
@@ -34,6 +34,9 @@ import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Property;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
import org.jetbrains.annotations.ApiStatus;
@@ -44,31 +47,77 @@ 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;
/**
* This is the public api available exposed to build scripts.
*/
public interface LoomGradleExtensionAPI {
- File getAccessWidener();
+ @ApiStatus.Internal
+ DeprecationHelper getDeprecationHelper();
+
+ RegularFileProperty getAccessWidenerPath();
+
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default File getAccessWidener() {
+ getDeprecationHelper().replaceWithInLoom0_11("accessWidener", "accessWidenerPath");
+ return getAccessWidenerPath().getAsFile().getOrNull();
+ }
+
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default void setAccessWidener(File file) {
+ getDeprecationHelper().replaceWithInLoom0_11("accessWidener", "accessWidenerPath");
+ getAccessWidenerPath().set(file);
+ }
- void setAccessWidener(Object file);
+ Property<Boolean> getShareRemapCaches();
- void setShareCaches(boolean shareCaches);
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default void setShareCaches(boolean shareCaches) {
+ getDeprecationHelper().replaceWithInLoom0_11("shareCaches", "shareRemapCaches");
+ getShareRemapCaches().set(shareCaches);
+ }
- boolean isShareCaches();
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default boolean isShareCaches() {
+ getDeprecationHelper().replaceWithInLoom0_11("shareCaches", "shareRemapCaches");
+ return getShareRemapCaches().get();
+ }
default void shareCaches() {
- setShareCaches(true);
+ getShareRemapCaches().set(true);
+ }
+
+ ListProperty<LoomDecompiler> getGameDecompilers();
+
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default List<LoomDecompiler> getDecompilers() {
+ getDeprecationHelper().replaceWithInLoom0_11("decompilers", "gameDecompilers");
+ return getGameDecompilers().get();
}
- List<LoomDecompiler> getDecompilers();
+ default void addDecompiler(LoomDecompiler decompiler) {
+ getGameDecompilers().add(decompiler);
+ }
- void addDecompiler(LoomDecompiler decompiler);
+ ListProperty<JarProcessor> getGameJarProcessors();
- List<JarProcessor> getJarProcessors();
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default List<JarProcessor> getJarProcessors() {
+ getDeprecationHelper().replaceWithInLoom0_11("jarProcessors", "gameJarProcessors");
+ return getGameJarProcessors().get();
+ }
- void addJarProcessor(JarProcessor processor);
+ default void addJarProcessor(JarProcessor processor) {
+ getGameJarProcessors().add(processor);
+ }
ConfigurableFileCollection getLog4jConfigs();
@@ -78,13 +127,35 @@ public interface LoomGradleExtensionAPI {
Dependency layered(Action<LayeredMappingSpecBuilder> action);
- String getRefmapName();
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default String getRefmapName() {
+ getDeprecationHelper().replaceWithInLoom0_11("refmapName", "mixin.defaultRefmapName");
+ return getMixin().getDefaultRefmapName().get();
+ }
+
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default void setRefmapName(String refmapName) {
+ getDeprecationHelper().replaceWithInLoom0_11("refmapName", "mixin.defaultRefmapName");
+ getMixin().getDefaultRefmapName().set(refmapName);
+ }
- void setRefmapName(String refmapName);
+ Property<Boolean> getRemapArchives();
- boolean isRemapMod();
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default boolean isRemapMod() {
+ getDeprecationHelper().replaceWithInLoom0_11("remapMod", "remapArchives");
+ return getRemapArchives().get();
+ }
- void setRemapMod(boolean remapMod);
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default void setRemapMod(boolean remapMod) {
+ getDeprecationHelper().replaceWithInLoom0_11("remapMod", "remapArchives");
+ getRemapArchives().set(remapMod);
+ }
void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action);
@@ -93,9 +164,24 @@ public interface LoomGradleExtensionAPI {
@ApiStatus.Experimental
void mixin(Action<MixinApExtensionAPI> action);
- void setCustomManifest(String customManifest);
+ @ApiStatus.Experimental
+ MixinApExtensionAPI getMixin();
+
+ Property<String> getCustomMinecraftManifest();
- String getCustomManifest();
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default void setCustomManifest(String customManifest) {
+ getDeprecationHelper().replaceWithInLoom0_11("customManifest", "customMinecraftManifest");
+ getCustomMinecraftManifest().set(customManifest);
+ }
+
+ @Deprecated(forRemoval = true)
+ @ApiStatus.ScheduledForRemoval(inVersion = "0.11")
+ default String getCustomManifest() {
+ getDeprecationHelper().replaceWithInLoom0_11("customManifest", "customMinecraftManifest");
+ return getCustomMinecraftManifest().getOrNull();
+ }
// ===================
// Architectury Loom
diff --git a/src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java
index 88b7fa79..e74eecbf 100644
--- a/src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java
+++ b/src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java
@@ -25,17 +25,19 @@
package net.fabricmc.loom.api;
import org.gradle.api.Action;
+import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Experimental
public interface MixinApExtensionAPI {
+ Property<String> getDefaultRefmapName();
+
/**
* Apply Mixin AP to sourceSet.
* @param sourceSet the sourceSet that applies Mixin AP.
- * @param refmapName the output ref-map name. By default this will
- * be {@link net.fabricmc.loom.LoomGradleExtension#getRefmapName()}
+ * @param refmapName the output ref-map name. By default this will be {@link #getDefaultRefmapName()}
* @param action used for filter the mixin json files. By default this will be all files
* with name {@code *.mixins.json} that is inside the {@code resources} folder
* of {@code sourceSet}.
diff --git a/src/main/java/net/fabricmc/loom/build/JarRemapper.java b/src/main/java/net/fabricmc/loom/build/JarRemapper.java
index d97bf925..5996401b 100644
--- a/src/main/java/net/fabricmc/loom/build/JarRemapper.java
+++ b/src/main/java/net/fabricmc/loom/build/JarRemapper.java
@@ -43,6 +43,7 @@ import org.gradle.api.Action;
import org.gradle.api.Project;
import org.objectweb.asm.commons.Remapper;
+import net.fabricmc.loom.util.CloseableList;
import net.fabricmc.loom.util.LoggerFilter;
import net.fabricmc.stitch.util.Pair;
@@ -101,31 +102,35 @@ public class JarRemapper {
}
}
- List<OutputConsumerPath> outputConsumers = new ArrayList<>();
+ //noinspection MismatchedQueryAndUpdateOfCollection
+ try (CloseableList<OutputConsumerPath> outputConsumers = new CloseableList<>()) {
+ for (RemapData data : remapData) {
+ OutputConsumerPath outputConsumer;
+ project.getLogger().info(":remapper output -> " + data.output.getFileName().toString());
- for (RemapData data : remapData) {
- OutputConsumerPath outputConsumer;
- project.getLogger().info(":remapper output -> " + data.output.getFileName().toString());
-
- try {
- Files.deleteIfExists(data.output);
- outputConsumer = new OutputConsumerPath.Builder(data.output).build();
- } catch (Exception e) {
- throw new RuntimeException("Failed to create remapper output " + data.output.getFileName().toString(), e);
- }
+ try {
+ Files.deleteIfExists(data.output);
+ outputConsumer = new OutputConsumerPath.Builder(data.output).build();
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create remapper output " + data.output.getFileName().toString(), e);
+ }
- outputConsumers.add(outputConsumer);
+ outputConsumers.add(outputConsumer);
- outputConsumer.addNonClassFiles(data.input);
+ outputConsumer.addNonClassFiles(data.input);
- data.processAccessWidener(remapper.getRemapper());
- remapper.apply(outputConsumer, data.tag);
- }
+ data.processAccessWidener(remapper.getRemapper());
+ remapper.apply(outputConsumer, data.tag);
+ }
- remapper.finish();
+ remapper.finish();
+ } catch (Exception e) {
+ for (RemapData data : remapData) {
+ // Cleanup bad outputs
+ Files.deleteIfExists(data.output);
+ }
- for (OutputConsumerPath outputConsumer : outputConsumers) {
- outputConsumer.close();
+ throw new IOException("Failed to remap %s files".formatted(remapData.size()), e);
}
remapData.forEach(RemapData::complete);
diff --git a/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java b/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java
index 458a5ffb..d7452267 100644
--- a/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java
+++ b/src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java
@@ -25,13 +25,23 @@
package net.fabricmc.loom.build;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Objects;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import org.gradle.api.Project;
+import org.jetbrains.annotations.NotNull;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
@@ -43,29 +53,78 @@ import net.fabricmc.loom.extension.MixinApExtension;
public final class MixinRefmapHelper {
private MixinRefmapHelper() { }
+ private static final String FABRIC_MOD_JSON = "fabric.mod.json";
+
public static boolean addRefmapName(Project project, Path outputPath) {
- MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension();
- File output = outputPath.toFile();
-
- return mixin.getMixinSourceSetsStream().map(sourceSet -> {
- MixinApExtension.MixinInformationContainer container = Objects.requireNonNull(
- MixinApExtension.getMixinInformationContainer(sourceSet)
- );
- Stream<String> mixinJsonNames = container.getMixinJsonNames();
- String refmapName = container.getRefmapName();
-
- return ZipUtil.transformEntries(output, mixinJsonNames.map(f -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
- @Override
- protected String transform(ZipEntry zipEntry, String input) {
- JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
-
- if (!json.has("refmap")) {
- json.addProperty("refmap", refmapName);
+ try {
+ MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
+ File output = outputPath.toFile();
+
+ Collection<String> allMixinConfigs = getMixinConfigurationFiles(readFabricModJson(output));
+
+ return mixin.getMixinSourceSetsStream().map(sourceSet -> {
+ MixinApExtension.MixinInformationContainer container = Objects.requireNonNull(
+ MixinApExtension.getMixinInformationContainer(sourceSet)
+ );
+
+ Stream<String> mixinConfigs = sourceSet.getResources()
+ .matching(container.mixinConfigPattern())
+ .getFiles()
+ .stream()
+ .map(File::getName)
+ .filter(allMixinConfigs::contains);
+
+ String refmapName = container.refmapNameProvider().get();
+
+ return ZipUtil.transformEntries(output, mixinConfigs.map(f -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
+ @Override
+ protected String transform(ZipEntry zipEntry, String input) {
+ JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
+
+ if (!json.has("refmap")) {
+ json.addProperty("refmap", refmapName);
+ }
+
+ return LoomGradlePlugin.GSON.toJson(json);
}
+ })).toArray(ZipEntryTransformerEntry[]::new));
+ }).reduce(false, Boolean::logicalOr);
+ } catch (Exception e) {
+ project.getLogger().error(e.getMessage());
+ return false;
+ }
+ }
+
+ @NotNull
+ private static JsonObject readFabricModJson(File output) {
+ try (ZipFile zip = new ZipFile(output)) {
+ ZipEntry entry = zip.getEntry(FABRIC_MOD_JSON);
+
+ try (InputStreamReader reader = new InputStreamReader(zip.getInputStream(entry))) {
+ return LoomGradlePlugin.GSON.fromJson(reader, JsonObject.class);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot read file fabric.mod.json in the output jar.", e);
+ }
+ }
- return LoomGradlePlugin.GSON.toJson(json);
- }
- })).toArray(ZipEntryTransformerEntry[]::new));
- }).reduce(false, Boolean::logicalOr);
+ @NotNull
+ private static Collection<String> getMixinConfigurationFiles(JsonObject fabricModJson) {
+ JsonArray mixins = fabricModJson.getAsJsonArray("mixins");
+
+ if (mixins == null) {
+ return Collections.emptySet();
+ }
+
+ return StreamSupport.stream(mixins.spliterator(), false)
+ .map(e -> {
+ if (e instanceof JsonPrimitive str) {
+ return str.getAsString();
+ } else if (e instanceof JsonObject obj) {
+ return obj.get("config").getAsString();
+ } else {
+ throw new RuntimeException("Incorrect fabric.mod.json format");
+ }
+ }).collect(Collectors.toSet());
}
}
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java
index a9dca7f0..210016ed 100644
--- a/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java
+++ b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java
@@ -65,7 +65,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
}
protected static Collection<Configuration> getApConfigurations(Project project, Function<String, String> getApConfigNameFunc) {
- MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension();
+ MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getApConfigurationsStream(getApConfigNameFunc).collect(Collectors.toList());
}
@@ -80,7 +80,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
private void passMixinArguments(T task, SourceSet sourceSet) {
try {
LoomGradleExtension loom = LoomGradleExtension.get(project);
- String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).getRefmapName();
+ String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
Map<String, String> args = new HashMap<>() {{
put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.getCanonicalPath());
put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, loom.getNextMixinMappings().getCanonicalPath());
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java
index a449600a..b1109f1c 100644
--- a/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java
+++ b/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java
@@ -46,7 +46,7 @@ public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
}
private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) {
- MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension();
+ MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue())));
}
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java
index 3fea3c6e..d49a473a 100644
--- a/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java
+++ b/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java
@@ -66,7 +66,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
}
private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) {
- MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension();
+ MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue())));
}
@@ -82,7 +82,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
SourceSet sourceSet = entry.getKey();
task.doLast(t -> {
try {
- String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).getRefmapName();
+ String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
Path src = Paths.get(getRefmapDestination(task, refmapName));
Path dest = Paths.get(task.getDestinationDir().toString(), refmapName);
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java
index 7a3238b7..8597cdd9 100644
--- a/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java
+++ b/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java
@@ -47,7 +47,7 @@ public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> {
}
private static Map<SourceSet, ScalaCompile> getInvokerTasks(Project project) {
- MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension();
+ MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.SCALA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((ScalaCompile) entry.getValue())));
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
index 42d6e0fd..e6589da5 100644
--- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
+++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
@@ -29,7 +29,6 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
-import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.jvm.tasks.Jar;
@@ -147,11 +146,6 @@ public final class CompileConfiguration {
Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
- p.getTasks().withType(JavaCompile.class).configureEach(compile -> {
- // Fork the java compiler to ensure that it does not keep any files open.
- compile.getOptions().setFork(true);
- });
-
p.afterEvaluate(project -> {
LoomGradleExtension extension = LoomGradleExtension.get(project);
@@ -186,9 +180,10 @@ public final class CompileConfiguration {
SetupIntelijRunConfigs.setup(project);
GenVsCodeProjectTask.generate(project);
+ extension.getRemapArchives().finalizeValue();
// Enables the default mod remapper
- if (extension.isRemapMod()) {
+ if (extension.getRemapArchives().get()) {
RemapConfiguration.setupDefaultRemap(project);
} else {
Jar jarTask = (Jar) project.getTasks().getByName("jar");
@@ -201,7 +196,7 @@ public final class CompileConfiguration {
System.setProperty("log4j.skipJansi", "true");
project.getLogger().info("Configuring compiler arguments for Java");
- MixinApExtension mixinApExtension = LoomGradleExtension.get(project).getMixinApExtension();
+ MixinApExtension mixinApExtension = LoomGradleExtension.get(project).getMixin();
mixinApExtension.init();
new JavaApInvoker(project).configureMixin();
diff --git a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java
index b0568731..b14d2678 100644
--- a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java
+++ b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java
@@ -25,6 +25,7 @@
package net.fabricmc.loom.configuration;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -170,7 +171,15 @@ public class LoomDependencyManager {
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, sourceRemapper);
- sourceRemapper.remapAll();
+ long start = System.currentTimeMillis();
+
+ try {
+ sourceRemapper.remapAll();
+ } catch (IOException exception) {
+ throw new RuntimeException("Failed to remap mod sources", exception);
+ }
+
+ project.getLogger().info("Source remapping took: %dms".formatted(System.currentTimeMillis() - start));
for (Runnable runnable : afterTasks) {
runnable.run();
diff --git a/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
index f8d45018..6afcf2c1 100644
--- a/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
+++ b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java
@@ -105,7 +105,7 @@ public class RemapConfiguration {
// TODO what is this for?
Task parentTask = project.getTasks().getByName("build");
- if (extension.isShareCaches()) {
+ if (extension.getShareRemapCaches().get()) {
Project rootProject = project.getRootProject();
if (extension.isRootProject()) {
@@ -116,7 +116,6 @@ public class RemapConfiguration {
rootProject.getTasks().register(remapAllSourcesTaskName, RemapAllSourcesTask.class, task -> {
task.sourceRemapper = sourceRemapper;
- task.doLast(t -> sourceRemapper.remapAll());
});
parentTask = rootProject.getTasks().getByName(remapAllSourcesTaskName);
@@ -165,7 +164,7 @@ public class RemapConfiguration {
});
}
- if (extension.isShareCaches()) {
+ if (extension.getShareRemapCaches().get()) {
remapSourcesJarTask.setSourceRemapper(remapper);
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java
index ef2f37e1..cecf4d34 100644
--- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java
+++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java
@@ -71,16 +71,22 @@ public class AccessWidenerJarProcessor implements JarProcessor {
}
@Override
+ public String getId() {
+ return "loom:access_widener";
+ }
+
+ @Override
public void setup() {
LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project);
+ File awPath = loomGradleExtension.getAccessWidenerPath().get().getAsFile();
- if (!loomGradleExtension.getAccessWidener().exists()) {
- throw new RuntimeException("Could not find access widener file @ " + loomGradleExtension.getAccessWidener().getAbsolutePath());
+ if (!awPath.exists()) {
+ throw new RuntimeException("Could not find access widener file @ " + awPath.getAbsolutePath());
}
- inputHash = Checksum.sha256(loomGradleExtension.getAccessWidener());
+ inputHash = Checksum.sha256(awPath);
- try (BufferedReader reader = new BufferedReader(new FileReader(loomGradleExtension.getAccessWidener()))) {
+ try (BufferedReader reader = new BufferedReader(new FileReader(awPath))) {
accessWidenerReader.read(reader);
} catch (IOException e) {
throw new RuntimeException("Failed to read project access widener file");
diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
index a9335764..8c60619f 100644
--- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
+++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
@@ -52,6 +52,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import net.fabricmc.loom.LoomGradleExtension;
+import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.util.OperatingSystem;
public class RunConfig {
@@ -269,7 +270,13 @@ public class RunConfig {
}
private static String getMainClass(String side, LoomGradleExtension extension, String defaultMainClass) {
- JsonObject installerJson = extension.getInstallerData() == null ? null : extension.getInstallerData().installerJson();
+ InstallerData installerData = extension.getInstallerData() == null ? null : extension.getInstallerData();
+
+ if (installerData == null) {
+ return defaultMainClass;
+ }
+
+ JsonObject installerJson = installerData.installerJson();
if (installerJson != null && installerJson.has("mainClass")) {
JsonElement mainClassJson = installerJson.get("mainClass");
diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java
index 33cde23b..71f9a6bf 100644
--- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java
+++ b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java
@@ -27,6 +27,18 @@ package net.fabricmc.loom.configuration.processors;
import java.io.File;
public interface JarProcessor {
+ /**
+ * Returns a unique ID for this jar processor, containing all configuration details.
+ *
+ * <p>If the jar processor implementation class supports creating multiple jar processors with different effects,
+ * the needed configuration should also be included in this ID. Example: {@code path.to.MyJarProcessor#someOption}.
+ *
+ * @return the ID of this jar processor
+ */
+ default String getId() {
+ return getClass().getName();
+ }
+
void setup();
/**
diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java
index 9ee6864d..4c36c40d 100644
--- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java
+++ b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java
@@ -25,9 +25,27 @@
package net.fabricmc.loom.configuration.processors;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+
+import com.google.common.hash.Hashing;
+import com.google.common.io.CharSource;
+import org.zeroturnaround.zip.ZipUtil;
+import org.zeroturnaround.zip.transform.StreamZipEntryTransformer;
+import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
public class JarProcessorManager {
+ private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
+ private static final String JAR_PROCESSOR_HASH_ATTRIBUTE = "Loom-Jar-Processor-Hash";
private final List<JarProcessor> jarProcessors;
public JarProcessorManager(List<JarProcessor> jarProcessors) {
@@ -47,13 +65,56 @@ public class JarProcessorManager {
return true;
}
+ String jarProcessorHash = getJarProcessorHash();
+
+ try (JarFile jar = new JarFile(file)) {
+ Attributes attributes = jar.getManifest().getMainAttributes();
+
+ if (!jarProcessorHash.equals(attributes.getValue(JAR_PROCESSOR_HASH_ATTRIBUTE))) {
+ return true;
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Could not check jar manifest of " + file, e);
+ }
+
return jarProcessors.stream().anyMatch(jarProcessor -> jarProcessor.isInvalid(file));
}
+ private String getJarProcessorHash() {
+ String jarProcessorIds = jarProcessors.stream()
+ .map(JarProcessor::getId)
+ .sorted()
+ .collect(Collectors.joining(";"));
+
+ try {
+ return CharSource.wrap(jarProcessorIds)
+ .asByteSource(StandardCharsets.UTF_8)
+ .hash(Hashing.sha256())
+ .toString();
+ } catch (IOException e) {
+ throw new UncheckedIOException("Could not hash jar processor IDs", e);
+ }
+ }
+
public void process(File file) {
for (JarProcessor jarProcessor : jarProcessors) {
jarProcessor.process(file);
}
+
+ boolean manifestTransformed = ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {
+ new ZipEntryTransformerEntry(MANIFEST_PATH, new StreamZipEntryTransformer() {
+ @Override
+ protected void transform(ZipEntry zipEntry, InputStream in, OutputStream out) throws IOException {
+ Manifest manifest = new Manifest(in);
+ manifest.getMainAttributes().putValue(JAR_PROCESSOR_HASH_ATTRIBUTE, getJarProcessorHash());
+ manifest.write(out);
+ }
+ })
+ });
+
+ if (!manifestTransformed) {
+ throw new RuntimeException("Could not add data to jar manifest in " + file);
+ }
}
public <T extends JarProcessor> T getByType(Class<T> tClass) {
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java
index fa6e5703..2ac31e06 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java
@@ -135,7 +135,7 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
}
private void downloadMcJson(boolean offline) throws IOException {
- if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) {
+ if (getExtension().getShareRemapCaches().get() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) {
return;
}
@@ -159,10 +159,10 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
- if (getExtension().getCustomManifest() != null) {
+ if (getExtension().getCustomMinecraftManifest().isPresent()) {
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
customVersion.id = minecraftVersion;
- customVersion.url = getExtension().getCustomManifest();
+ customVersion.url = getExtension().getCustomMinecraftManifest().get();
optionalVersion = Optional.of(customVersion);
getProject().getLogger().lifecycle("Using custom minecraft manifest");
}
@@ -226,7 +226,7 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
}
private boolean hasRecentValidManifest() throws IOException {
- if (getExtension().getCustomManifest() != null) {
+ if (getExtension().getCustomMinecraftManifest().isPresent()) {
return false;
}
@@ -247,7 +247,7 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
}
private void downloadJars(Logger logger) throws IOException {
- if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) {
+ if (getExtension().getShareRemapCaches().get() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) {
return;
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
index db478671..ced88424 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java
@@ -25,8 +25,9 @@
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.File;
-import java.util.function.Supplier;
+import java.io.IOException;
+import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.logging.Logger;
@@ -37,12 +38,11 @@ import net.fabricmc.loom.configuration.providers.MinecraftProvider;
public class GradleMappingContext implements MappingContext {
private final Project project;
private final LoomGradleExtension extension;
- private final Supplier<String> workingDirName;
+ private File workingDir;
- public GradleMappingContext(Project project, Supplier<String> workingDirName) {
+ public GradleMappingContext(Project project) {
this.project = project;
this.extension = LoomGradleExtension.get(project);
- this.workingDirName = workingDirName;
}
@Override
@@ -62,10 +62,28 @@ public class GradleMappingContext implements MappingContext {
}
@Override
+ public File workingDirectory() {
+ if (workingDir == null) {
+ workingDir = new File(mappingsProvider().getMappingsDir().toFile(), "layered/" + minecraftProvider().minecraftVersion());
+
+ if (workingDir.exists()) {
+ try {
+ FileUtils.deleteDirectory(workingDir);
+ } catch (IOException e) {
+ getLogger().warn("Failed to cleanup layered mappings working directory: {}", e.getMessage());
+ }
+ }
+ }
+
+ return workingDir;
+ }
+
+ @Override
public File workingDirectory(String name) {
- File tempDir = new File(mappingsProvider().getMappingsDir().toFile(), workingDirName.get());
- tempDir.mkdirs();
- return new File(tempDir, name);
+ File file = new File(workingDirectory(), name);
+ file.mkdirs();
+
+ return file;
}
@Override
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java
index 2e47af39..f42a3289 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java
@@ -27,8 +27,8 @@ package net.fabricmc.loom.configuration.providers.mappings;
import java.util.List;
public record LayeredMappingSpec(List<MappingsSpec<?>> layers) {
- public String getVersion() {
+ public String getVersion(MappingContext context) {
// TODO something better?
- return "layered+hash.%d".formatted(Math.abs(hashCode()));
+ return "layered+hash.%d.minecraft.%s".formatted(Math.abs(hashCode()), context.minecraftVersion());
}
}
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
index 1b5d673f..b253a114 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java
@@ -54,17 +54,16 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
private final MappingContext mappingContext;
private final LayeredMappingSpec layeredMappingSpec;
- private final String version;
+ private String version = null;
- public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) {
+ public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec) {
this.mappingContext = mappingContext;
this.layeredMappingSpec = layeredMappingSpec;
- this.version = version;
}
@Override
public Set<File> resolve() {
- Path mappingsDir = mappingContext.mappingsProvider().getMappingsDir();
+ Path mappingsDir = mappingContext.workingDirectory().toPath();
Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion()));
if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) {
@@ -115,6 +114,10 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
@Override
public String getVersion() {
+ if (version == null) {
+ version = layeredMappingSpec.getVersion(mappingContext);
+ }
+
return version;
}
@@ -129,7 +132,7 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
@Override
public Dependency copy() {
- return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version);
+ return new LayeredMappingsDependency(mappingContext, layeredMappingSpec);
}
@Override
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java
index 3fbfb655..0ccd61ea 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java
@@ -41,6 +41,8 @@ public interface MappingContext {
return minecraftProvider().minecraftVersion();
}
+ File workingDirectory();
+
/**
* Creates a temporary working dir to be used to store working files.
*/
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 1de460e8..f15f6eca 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
@@ -277,11 +277,13 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
LoomGradleExtension extension = getExtension();
- if (extension.getAccessWidener() != null) {
- extension.addJarProcessor(new AccessWidenerJarProcessor(getProject()));
+ if (extension.getAccessWidenerPath().isPresent()) {
+ extension.getGameJarProcessors().add(new AccessWidenerJarProcessor(getProject()));
}
- JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors());
+ extension.getAccessWidenerPath().finalizeValue();
+ extension.getGameJarProcessors().finalizeValue();
+ JarProcessorManager processorManager = new JarProcessorManager(extension.getGameJarProcessors().get());
extension.setJarProcessorManager(processorManager);
processorManager.setupProcessors();
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java
index 251ff986..4b4d407b 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java
@@ -44,15 +44,16 @@ import net.fabricmc.mappingio.MappingVisitor;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.ProGuardReader;
-public record MojangMappingLayer(MinecraftVersionMeta.Download clientDownload,
+public record MojangMappingLayer(String minecraftVersion,
+ MinecraftVersionMeta.Download clientDownload,
MinecraftVersionMeta.Download serverDownload,
File workingDir,
Logger logger,
MojangMappingsSpec.SilenceLicenseOption silenceLicense) implements MappingLayer {
@Override
public void visit(MappingVisitor mappingVisitor) throws IOException {
- var clientMappings = new File(workingDir(), "client.txt");
- var serverMappings = new File(workingDir(), "server.txt");
+ var clientMappings = new File(workingDir(), "%s.client.txt".formatted(minecraftVersion));
+ var serverMappings = new File(workingDir(), "%s.server.txt".formatted(minecraftVersion));
download(clientMappings, serverMappings);
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java
index 67f22460..f304530f 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java
@@ -78,6 +78,7 @@ public record MojangMappingsSpec(SilenceLicenseOption silenceLicense) implements
}
return new MojangMappingLayer(
+ context.minecraftVersion(),
versionInfo.download(MANIFEST_CLIENT_MAPPINGS),
versionInfo.download(MANIFEST_SERVER_MAPPINGS),
context.workingDirectory("mojang"),
diff --git a/src/main/java/net/fabricmc/loom/decompilers/DecompilerConfiguration.java b/src/main/java/net/fabricmc/loom/decompilers/DecompilerConfiguration.java
index 40380a4d..bd51c4e8 100644
--- a/src/main/java/net/fabricmc/loom/decompilers/DecompilerConfiguration.java
+++ b/src/main/java/net/fabricmc/loom/decompilers/DecompilerConfiguration.java
@@ -36,7 +36,7 @@ public final class DecompilerConfiguration {
public static void setup(Project project) {
LoomGradleExtension extension = LoomGradleExtension.get(project);
- extension.addDecompiler(new FabricFernFlowerDecompiler(project));
- extension.addDecompiler(new FabricCFRDecompiler(project));
+ extension.getGameDecompilers().add(new FabricFernFlowerDecompiler(project));
+ extension.getGameDecompilers().add(new FabricCFRDecompiler(project));
}
}
diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
index bf262615..e2a12f45 100644
--- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
@@ -24,15 +24,6 @@
package net.fabricmc.loom.extension;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -42,7 +33,10 @@ import org.gradle.api.NamedDomainObjectContainer;
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.BasePluginConvention;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Property;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
@@ -58,6 +52,7 @@ 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.LayeredMappingsDependency;
+import net.fabricmc.loom.util.DeprecationHelper;
import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.function.LazyBool;
@@ -69,15 +64,14 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
private static final String PLATFORM_PROPERTY = "loom.platform";
private static final String INCLUDE_PROPERTY = "loom.forge.include";
- protected final List<LoomDecompiler> decompilers = new ArrayList<>();
- protected final List<JarProcessor> jarProcessors = new ArrayList<>();
+ protected final DeprecationHelper deprecationHelper;
+ protected final ListProperty<LoomDecompiler> decompilers;
+ protected final ListProperty<JarProcessor> jarProcessors;
protected final ConfigurableFileCollection log4jConfigs;
-
- protected File accessWidener = null;
- protected boolean shareCaches = false;
- protected String refmapName = null;
- protected boolean remapMod = true;
- protected String customManifest;
+ protected final RegularFileProperty accessWidener;
+ protected final Property<Boolean> shareCaches;
+ protected final Property<Boolean> remapArchives;
+ protected final Property<String> customManifest;
private NamedDomainObjectContainer<RunConfigSettings> runConfigs;
@@ -101,7 +95,19 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected LoomGradleExtensionApiImpl(Project project, LoomFiles directories) {
this.runConfigs = project.container(RunConfigSettings.class,
baseName -> new RunConfigSettings(project, baseName));
+ this.decompilers = project.getObjects().listProperty(LoomDecompiler.class)
+ .empty();
+ this.jarProcessors = project.getObjects().listProperty(JarProcessor.class)
+ .empty();
this.log4jConfigs = project.files(directories.getDefaultLog4jConfigFile());
+ this.accessWidener = project.getObjects().fileProperty();
+ this.shareCaches = project.getObjects().property(Boolean.class)
+ .convention(false);
+ this.remapArchives = project.getObjects().property(Boolean.class)
+ .convention(true);
+ this.customManifest = project.getObjects().property(String.class);
+
+ this.deprecationHelper = new DeprecationHelper.ProjectBased(project);
this.platform = project.getObjects().property(ModPlatform.class).convention(project.provider(Suppliers.memoize(() -> {
Object platformProperty = project.findProperty(PLATFORM_PROPERTY);
@@ -124,61 +130,46 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
- public File getAccessWidener() {
- return accessWidener;
+ public DeprecationHelper getDeprecationHelper() {
+ return deprecationHelper;
}
@Override
- public void setAccessWidener(Object file) {
- Objects.requireNonNull(file, "Access widener file cannot be null");
- this.accessWidener = getProject().file(file);
- }
-
- @Override
- public void setShareCaches(boolean shareCaches) {
- this.shareCaches = shareCaches;
+ public RegularFileProperty getAccessWidenerPath() {
+ return accessWidener;
}
@Override
- public boolean isShareCaches() {
+ public Property<Boolean> getShareRemapCaches() {
return shareCaches;
}
@Override
- public List<LoomDecompiler> getDecompilers() {
+ public ListProperty<LoomDecompiler> getGameDecompilers() {
return decompilers;
}
@Override
- public void addDecompiler(LoomDecompiler decompiler) {
- Objects.requireNonNull(decompiler, "Decompiler cannot be null");
- decompilers.add(decompiler);
- }
-
- @Override
- public List<JarProcessor> getJarProcessors() {
+ public ListProperty<JarProcessor> getGameJarProcessors() {
return jarProcessors;
}
@Override
- public void addJarProcessor(JarProcessor processor) {
- Objects.requireNonNull(processor, "Jar processor cannot be null");
- jarProcessors.add(processor);
- }
-
- @Override
public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this);
action.execute(builder);
LayeredMappingSpec builtSpec = builder.build();
- return new LayeredMappingsDependency(new GradleMappingContext(getProject(), () -> {
- return "layers/" + getMinecraftVersion() + "_" + builtSpec.getVersion().replace("+", "_").replace(".", "_");
- }), builtSpec, builtSpec.getVersion());
+ return new LayeredMappingsDependency(new GradleMappingContext(getProject()), builtSpec);
}
protected abstract String getMinecraftVersion();
@Override
+ public Property<Boolean> getRemapArchives() {
+ return remapArchives;
+ }
+
+ @Override
public String getRefmapName() {
if (refmapName == null || refmapName.isEmpty()) {
String defaultRefmapName;
@@ -197,16 +188,6 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
- public void setRefmapName(String refmapName) {
- this.refmapName = refmapName;
- }
-
- @Override
- public void setRemapMod(boolean remapMod) {
- this.remapMod = remapMod;
- }
-
- @Override
public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) {
action.execute(runConfigs);
}
@@ -222,23 +203,12 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
- public boolean isRemapMod() {
- return remapMod;
- }
-
- @Override
public void mixin(Action<MixinApExtensionAPI> action) {
- action.execute(getMixinApExtension());
+ action.execute(getMixin());
}
@Override
- public void setCustomManifest(String customManifest) {
- Objects.requireNonNull(customManifest, "Custom manifest cannot be null");
- this.customManifest = customManifest;
- }
-
- @Override
- public String getCustomManifest() {
+ public Property<String> getCustomMinecraftManifest() {
return customManifest;
}
@@ -246,8 +216,6 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected abstract LoomFiles getFiles();
- protected abstract MixinApExtension getMixinApExtension();
-
@Override
public void silentMojangMappingsLicense() {
this.silentMojangMappingsLicense = true;
@@ -390,6 +358,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
+ public DeprecationHelper getDeprecationHelper() {
+ throw new RuntimeException("Yeah... something is really wrong");
+ }
+
+ @Override
protected Project getProject() {
throw new RuntimeException("Yeah... something is really wrong");
}
@@ -400,7 +373,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
}
@Override
- protected MixinApExtension getMixinApExtension() {
+ public MixinApExtension getMixin() {
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 e97a6e3c..feb6bc21 100644
--- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
@@ -63,7 +63,8 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
public LoomGradleExtensionImpl(Project project, LoomFiles files) {
super(project, files);
this.project = project;
- this.mixinApExtension = new MixinApExtensionImpl(project);
+ // Initiate with newInstance to allow gradle to decorate our extension
+ this.mixinApExtension = project.getObjects().newInstance(MixinApExtensionImpl.class, project);
this.loomFiles = files;
this.unmappedMods = project.files();
}
@@ -166,7 +167,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
}
@Override
- public MixinApExtension getMixinApExtension() {
+ public MixinApExtension getMixin() {
return this.mixinApExtension;
}
diff --git a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
new file mode 100644
index 00000000..ae4804f7
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
@@ -0,0 +1,134 @@
+/*
+ * 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 org.gradle.api.Action;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.RegularFileProperty;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Property;
+
+import net.fabricmc.loom.api.LoomGradleExtensionAPI;
+import net.fabricmc.loom.api.MixinApExtensionAPI;
+import net.fabricmc.loom.api.decompilers.LoomDecompiler;
+import net.fabricmc.loom.configuration.ide.RunConfigSettings;
+import net.fabricmc.loom.configuration.processors.JarProcessor;
+import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
+import net.fabricmc.loom.util.DeprecationHelper;
+
+public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
+ private final LoomGradleExtensionAPI parent;
+ private boolean deprecationReported = false;
+
+ public MinecraftGradleExtension(LoomGradleExtensionAPI parent) {
+ this.parent = parent;
+ }
+
+ private void reportDeprecation() {
+ if (!deprecationReported) {
+ getDeprecationHelper().replaceWithInLoom0_11("minecraft", "loom");
+ deprecationReported = true;
+ }
+ }
+
+ @Override
+ public DeprecationHelper getDeprecationHelper() {
+ return parent.getDeprecationHelper();
+ }
+
+ @Override
+ public RegularFileProperty getAccessWidenerPath() {
+ reportDeprecation();
+ return parent.getAccessWidenerPath();
+ }
+
+ @Override
+ public Property<Boolean> getShareRemapCaches() {
+ reportDeprecation();
+ return parent.getShareRemapCaches();
+ }
+
+ @Override
+ public ListProperty<LoomDecompiler> getGameDecompilers() {
+ reportDeprecation();
+ return parent.getGameDecompilers();
+ }
+
+ @Override
+ public ListProperty<JarProcessor> getGameJarProcessors() {
+ reportDeprecation();
+ return parent.getGameJarProcessors();
+ }
+
+ @Override
+ public ConfigurableFileCollection getLog4jConfigs() {
+ reportDeprecation();
+ return parent.getLog4jConfigs();
+ }
+
+ @Override
+ public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
+ reportDeprecation();
+ return parent.layered(action);
+ }
+
+ @Override
+ public Property<Boolean> getRemapArchives() {
+ reportDeprecation();
+ return parent.getRemapArchives();
+ }
+
+ @Override
+ public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) {
+ reportDeprecation();
+ parent.runs(action);
+ }
+
+ @Override
+ public NamedDomainObjectContainer<RunConfigSettings> getRunConfigs() {
+ reportDeprecation();
+ return parent.getRunConfigs();
+ }
+
+ @Override
+ public void mixin(Action<MixinApExtensionAPI> action) {
+ reportDeprecation();
+ parent.mixin(action);
+ }
+
+ @Override
+ public MixinApExtensionAPI getMixin() {
+ reportDeprecation();
+ return parent.getMixin();
+ }
+
+ @Override
+ public Property<String> getCustomMinecraftManifest() {
+ reportDeprecation();
+ return parent.getCustomMinecraftManifest();
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/extension/MixinApExtension.java b/src/main/java/net/fabricmc/loom/extension/MixinApExtension.java
index e63700b1..73e78858 100644
--- a/src/main/java/net/fabricmc/loom/extension/MixinApExtension.java
+++ b/src/main/java/net/fabricmc/loom/extension/MixinApExtension.java
@@ -26,7 +26,6 @@ package net.fabricmc.loom.extension;
import java.util.Collection;
import java.util.Map;
-import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -34,6 +33,7 @@ import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.plugins.ExtraPropertiesExtension;
+import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet;
@@ -55,42 +55,7 @@ public interface MixinApExtension extends MixinApExtensionAPI {
* for configuring the mixin annotation processor. It's stored
* in [SourceSet].ext.mixin.
*/
- final class MixinInformationContainer {
- private final SourceSet sourceSet;
- private final String refmapName;
- private Stream<String> mixinJsonNames;
-
- final PatternSet mixinJsonPattern;
-
- public MixinInformationContainer(@NotNull SourceSet sourceSet,
- @NotNull String refmapName,
- @NotNull PatternSet mixinJsonPattern) {
- this.sourceSet = sourceSet;
- this.refmapName = refmapName;
- this.mixinJsonPattern = mixinJsonPattern;
- }
-
- void setMixinJsonNames(@NotNull Stream<String> mixinJsonNames) {
- if (this.mixinJsonNames == null) {
- this.mixinJsonNames = mixinJsonNames;
- }
- }
-
- @NotNull
- public Stream<String> getMixinJsonNames() {
- return Objects.requireNonNull(mixinJsonNames);
- }
-
- @NotNull
- public SourceSet getSourceSet() {
- return sourceSet;
- }
-
- @NotNull
- public String getRefmapName() {
- return refmapName;
- }
- }
+ record MixinInformationContainer(SourceSet sourceSet, Provider<String> refmapNameProvider, PatternSet mixinConfigPattern) { }
@Nullable
static MixinInformationContainer getMixinInformationContainer(SourceSet sourceSet) {
diff --git a/src/main/java/net/fabricmc/loom/extension/MixinApExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/MixinApExtensionApiImpl.java
index 76326380..db06c481 100644
--- a/src/main/java/net/fabricmc/loom/extension/MixinApExtensionApiImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/MixinApExtensionApiImpl.java
@@ -28,15 +28,21 @@ import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet;
-import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.MixinApExtensionAPI;
public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
protected abstract Project getProject();
- protected abstract PatternSet add0(SourceSet sourceSet, String refmapName);
+
+ protected final PatternSet add0(SourceSet sourceSet, String refmapName) {
+ return add0(sourceSet, getProject().provider(() -> refmapName));
+ }
+
+ protected abstract PatternSet add0(SourceSet sourceSet, Provider<String> refmapName);
@Override
public void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action) {
@@ -51,14 +57,14 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
@Override
public void add(String sourceSetName, String refmapName, Action<PatternSet> action) {
- // try to find sourceSet with name sourceSetName in this project
- SourceSet sourceSet = getProject().getConvention().getPlugin(JavaPluginConvention.class)
- .getSourceSets().findByName(sourceSetName);
+ add(sourceSetName, getProject().provider(() -> refmapName), action);
+ }
- if (sourceSet == null) {
- throw new InvalidUserDataException("No sourceSet " + sourceSetName + " was found");
- }
+ public void add(String sourceSetName, Provider<String> refmapName, Action<PatternSet> action) {
+ add(resolveSourceSet(sourceSetName), refmapName, action);
+ }
+ public void add(SourceSet sourceSet, Provider<String> refmapName, Action<PatternSet> action) {
PatternSet pattern = add0(sourceSet, refmapName);
action.execute(pattern);
}
@@ -70,8 +76,7 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
@Override
public void add(SourceSet sourceSet, Action<PatternSet> action) {
- LoomGradleExtension extension = LoomGradleExtension.get(getProject());
- add(sourceSet, extension.getRefmapName(), action);
+ add(sourceSet, getDefaultRefmapName(), action);
}
@Override
@@ -81,8 +86,7 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
@Override
public void add(String sourceSetName, Action<PatternSet> action) {
- LoomGradleExtension extension = LoomGradleExtension.get(getProject());
- add(sourceSetName, extension.getRefmapName(), action);
+ add(sourceSetName, getDefaultRefmapName(), action);
}
@Override
@@ -90,6 +94,18 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
add(sourceSetName, x -> { });
}
+ private SourceSet resolveSourceSet(String sourceSetName) {
+ // try to find sourceSet with name sourceSetName in this project
+ SourceSet sourceSet = getProject().getConvention().getPlugin(JavaPluginConvention.class)
+ .getSourceSets().findByName(sourceSetName);
+
+ if (sourceSet == null) {
+ throw new InvalidUserDataException("No sourceSet " + sourceSetName + " was found");
+ }
+
+ return sourceSet;
+ }
+
// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
private final class EnsureCompile extends MixinApExtensionApiImpl {
private EnsureCompile() {
@@ -103,7 +119,12 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
}
@Override
- protected PatternSet add0(SourceSet sourceSet, String refmapName) {
+ public Property<String> getDefaultRefmapName() {
+ throw new RuntimeException("Yeah... something is really wrong");
+ }
+
+ @Override
+ protected PatternSet add0(SourceSet sourceSet, Provider<String> refmapName) {
throw new RuntimeException("Yeah... something is really wrong");
}
}
diff --git a/src/main/java/net/fabricmc/loom/extension/MixinApExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/MixinApExtensionImpl.java
index fd541106..3602e75a 100644
--- a/src/main/java/net/fabricmc/loom/extension/MixinApExtensionImpl.java
+++ b/src/main/java/net/fabricmc/loom/extension/MixinApExtensionImpl.java
@@ -24,7 +24,6 @@
package net.fabricmc.loom.extension;
-import java.io.File;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
@@ -33,11 +32,16 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.inject.Inject;
+
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException;
import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.plugins.BasePluginConvention;
import org.gradle.api.plugins.JavaPluginConvention;
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet;
@@ -46,10 +50,14 @@ import org.jetbrains.annotations.NotNull;
public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements MixinApExtension {
private boolean isDefault;
private final Project project;
+ private final Property<String> defaultRefmapName;
+ @Inject
public MixinApExtensionImpl(Project project) {
this.isDefault = true;
this.project = project;
+ this.defaultRefmapName = project.getObjects().property(String.class)
+ .convention(project.provider(this::getDefaultMixinRefmapName));
}
@Override
@@ -58,8 +66,19 @@ public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements Mix
}
@Override
- protected PatternSet add0(SourceSet sourceSet, String refmapName) {
- PatternSet pattern = new PatternSet().setIncludes(Collections.singletonList("*.mixins.json"));
+ public Property<String> getDefaultRefmapName() {
+ return defaultRefmapName;
+ }
+
+ private String getDefaultMixinRefmapName() {
+ String defaultRefmapName = getProject().getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
+ getProject().getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
+ return defaultRefmapName;
+ }
+
+ @Override
+ protected PatternSet add0(SourceSet sourceSet, Provider<String> refmapName) {
+ PatternSet pattern = new PatternSet().setIncludes(Collections.singletonList("*.json"));
MixinApExtension.setMixinInformationContainer(sourceSet, new MixinApExtension.MixinInformationContainer(sourceSet, refmapName, pattern));
isDefault = false;
@@ -71,19 +90,7 @@ public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements Mix
@NotNull
public Stream<SourceSet> getMixinSourceSetsStream() {
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().stream()
- .filter(sourceSet -> {
- MixinApExtension.MixinInformationContainer container = MixinApExtension.getMixinInformationContainer(sourceSet);
-
- if (container != null) {
- PatternSet pattern = container.mixinJsonPattern;
- Stream<String> mixinJsonNames = sourceSet.getResources()
- .matching(pattern).getFiles().stream().map(File::getName);
- container.setMixinJsonNames(mixinJsonNames);
- return true;
- }
-
- return false;
- });
+ .filter(sourceSet -> MixinApExtension.getMixinInformationContainer(sourceSet) != null);
}
@Override
diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java
index cad89ae8..796ac49f 100644
--- a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java
+++ b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java
@@ -42,7 +42,7 @@ public abstract class AbstractRunTask extends JavaExec {
public AbstractRunTask(Function<Project, RunConfig> configProvider) {
super();
- setGroup(Constants.TASK_CATEGORY);
+ setGroup(Constants.TaskGroup.FABRIC);
this.config = configProvider.apply(getProject());
setClasspath(config.sourceSet.getRuntimeClasspath());
diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java
index e4bf8a54..883169f8 100644
--- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java
+++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java
@@ -51,7 +51,7 @@ public final class LoomTasks {
tasks.register("remapJar", RemapJarTask.class, t -> {
t.setDescription("Remaps the built project jar to intermediary mappings.");
- t.setGroup(Constants.TASK_CATEGORY);
+ t.setGroup(Constants.TaskGroup.FABRIC);
});
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric."));
@@ -67,24 +67,24 @@ public final class LoomTasks {
tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> {
t.setDescription("Generates an IntelliJ IDEA workspace from this project.");
t.dependsOn("idea", "downloadAssets");
- t.setGroup("ide");
+ t.setGroup(Constants.TaskGroup.IDE);
});
tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> {
t.setDescription("Generates Eclipse run configurations for this project.");
t.dependsOn("downloadAssets");
- t.setGroup("ide");
+ t.setGroup(Constants.TaskGroup.IDE);
});
tasks.register("cleanEclipseRuns", CleanEclipseRunsTask.class, t -> {
t.setDescription("Removes Eclipse run configurations for this project.");
- t.setGroup("ide");
+ t.setGroup(Constants.TaskGroup.IDE);
});
tasks.register("vscode", GenVsCodeProjectTask.class, t -> {
t.setDescription("Generates VSCode launch configurations.");
t.dependsOn("downloadAssets");
- t.setGroup("ide");
+ t.setGroup(Constants.TaskGroup.IDE);
});
}
@@ -148,7 +148,9 @@ public final class LoomTasks {
inputJar = outputJar;
}
- for (LoomDecompiler decompiler : extension.getDecompilers()) {
+ extension.getGameDecompilers().finalizeValue();
+
+ for (LoomDecompiler decompiler : extension.getGameDecompilers().get()) {
String taskName = decompiler instanceof FabricFernFlowerDecompiler ? "genSources" : "genSourcesWith" + decompiler.name();
// decompiler will be passed to the constructor of GenerateSourcesTask
GenerateSourcesTask generateSourcesTask = tasks.register(taskName, GenerateSourcesTask.class, decompiler).get();
diff --git a/src/main/java/net/fabricmc/loom/task/RemapAllSourcesTask.java b/src/main/java/net/fabricmc/loom/task/RemapAllSourcesTask.java
index 62bff631..4a9a44cf 100644
--- a/src/main/java/net/fabricmc/loom/task/RemapAllSourcesTask.java
+++ b/src/main/java/net/fabricmc/loom/task/RemapAllSourcesTask.java
@@ -24,7 +24,10 @@
package net.fabricmc.loom.task;
+import java.io.IOException;
+
import org.gradle.api.tasks.Internal;
+import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.util.SourceRemapper;
@@ -35,4 +38,13 @@ public class RemapAllSourcesTask extends AbstractLoomTask {
public SourceRemapper getSourceRemapper() {
return sourceRemapper;
}
+
+ @TaskAction
+ public void remap() {
+ try {
+ sourceRemapper.remapAll();
+ } catch (IOException exception) {
+ throw new RuntimeException("Failed to remap mod", exception);
+ }
+ }
}
diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
index 1c0a993c..f202b7f7 100644
--- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
+++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java
@@ -248,7 +248,7 @@ public class RemapJarTask extends Jar {
jarRemapper.scheduleRemap(input, output)
.supplyAccessWidener((remapData, remapper) -> {
- if (getRemapAccessWidener().getOrElse(false) && extension.getAccessWidener() != null) {
+ if (getRemapAccessWidener().getOrElse(false) && extension.getAccessWidenerPath().isPresent()) {
AccessWidenerJarProcessor accessWidenerJarProcessor = extension.getJarProcessorManager().getByType(AccessWidenerJarProcessor.class);
byte[] data;
diff --git a/src/main/java/net/fabricmc/loom/util/CloseableList.java b/src/main/java/net/fabricmc/loom/util/CloseableList.java
new file mode 100644
index 00000000..3d8ebf09
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/CloseableList.java
@@ -0,0 +1,52 @@
+/*
+ * 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.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class CloseableList<T extends Closeable> extends ArrayList<T> implements Closeable {
+ @Override
+ public void close() throws IOException {
+ IOException exception = null;
+
+ for (T t : this) {
+ try {
+ t.close();
+ } catch (IOException e) {
+ if (exception == null) {
+ exception = new IOException("Failed to close list");
+ }
+
+ exception.addSuppressed(e);
+ }
+ }
+
+ if (exception != null) {
+ throw exception;
+ }
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java
index 7d46245f..e7fdea26 100644
--- a/src/main/java/net/fabricmc/loom/util/Constants.java
+++ b/src/main/java/net/fabricmc/loom/util/Constants.java
@@ -40,7 +40,6 @@ public class Constants {
public static final String EXPERIMENTAL_VERSIONS = "https://maven.fabricmc.net/net/minecraft/experimental_versions.json";
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
- public static final String TASK_CATEGORY = "loom";
public static final int ASM_VERSION = Opcodes.ASM9;
@@ -136,6 +135,14 @@ public class Constants {
}
}
+ public static final class TaskGroup {
+ public static final String FABRIC = "loom";
+ public static final String IDE = "ide";
+
+ private TaskGroup() {
+ }
+ }
+
public static final class ForgeUserDev {
public static final String LAUNCH_TESTING = "net.minecraftforge.userdev.LaunchTesting";
diff --git a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java
new file mode 100644
index 00000000..f38c9022
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java
@@ -0,0 +1,86 @@
+/*
+ * 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.util.concurrent.atomic.AtomicBoolean;
+
+import org.gradle.api.Project;
+import org.gradle.api.logging.LogLevel;
+import org.gradle.api.logging.configuration.WarningMode;
+
+public interface DeprecationHelper {
+ default void replaceWithInLoom0_10(String currentName, String newName) {
+ toBeRemovedIn(currentName, newName, "Loom 0.10");
+ }
+
+ default void replaceWithInLoom0_11(String currentName, String newName) {
+ toBeRemovedIn(currentName, newName, "Loom 0.11");
+ }
+
+ default void replaceWithInLoom0_12(String currentName, String newName) {
+ toBeRemovedIn(currentName, newName, "Loom 0.12");
+ }
+
+ default void toBeRemovedIn(String currentName, String newName, String removalVersion) {
+ warn("The '%s' property has been deprecated, and has been replaced with '%s'. This is scheduled to be removed in %s.".formatted(currentName, newName, removalVersion));
+ }
+
+ Project getProject();
+
+ void warn(String warning);
+
+ class ProjectBased implements DeprecationHelper {
+ private final Project project;
+ private final AtomicBoolean usingDeprecatedApi = new AtomicBoolean(false);
+
+ public ProjectBased(Project project) {
+ this.project = project;
+
+ project.getGradle().buildFinished(buildResult -> {
+ if (usingDeprecatedApi.get()) {
+ project.getLogger().lifecycle("Deprecated Loom APIs were used in this build, making it incompatible with future versions of Loom. "
+ + "Use Gradle warning modes to control the verbosity of the warnings.");
+ }
+ });
+ }
+
+ @Override
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public void warn(String warning) {
+ WarningMode warningMode = getProject().getGradle().getStartParameter().getWarningMode();
+ getProject().getLogger().log(warningMode == WarningMode.None ? LogLevel.INFO : LogLevel.WARN, warning);
+
+ if (warningMode == WarningMode.Fail) {
+ throw new UnsupportedOperationException(warning);
+ }
+
+ usingDeprecatedApi.set(true);
+ }
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java
index ef9e61b0..c7bc394c 100644
--- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java
+++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java
@@ -29,15 +29,23 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
-import java.util.function.Consumer;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import com.google.common.base.Stopwatch;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
+import org.cadixdev.mercury.SourceProcessor;
import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.gradle.api.Project;
+import org.gradle.api.plugins.JavaPlugin;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
@@ -52,9 +60,8 @@ public class SourceRemapper {
private final Project project;
private String from;
private String to;
- private final List<Consumer<Mercury>> remapTasks = new ArrayList<>();
-
- private Mercury mercury;
+ private final List<RemapTask> remapTasks = new ArrayList<>();
+ private boolean hasStartedRemap = false;
public SourceRemapper(Project project, boolean named) {
this(project, named ? intermediary(project) : "named", !named ? intermediary(project) : "named");
@@ -71,106 +78,165 @@ public class SourceRemapper {
this.to = to;
}
- public static void remapSources(Project project, File input, File output, String from, String to, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
+ public static void remapSources(Project project, File input, File output, String from, String to, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws IOException {
SourceRemapper sourceRemapper = new SourceRemapper(project, from, to);
sourceRemapper.scheduleRemapSources(input, output, reproducibleFileOrder, preserveFileTimestamps);
sourceRemapper.remapAll();
}
public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
- remapTasks.add((mercury) -> {
- try {
- remapSourcesInner(mercury, source, destination);
- ZipReprocessorUtil.reprocessZip(destination, reproducibleFileOrder, preserveFileTimestamps);
+ this.scheduleRemapSources(new RemapTask(source, destination, reproducibleFileOrder, preserveFileTimestamps));
+ }
- // Set the remapped sources creation date to match the sources if we're likely succeeded in making it
- destination.setLastModified(source.lastModified());
- } catch (Exception e) {
- // Failed to remap, lets clean up to ensure we try again next time
- destination.delete();
- throw new RuntimeException("Failed to remap sources for " + source, e);
- }
- });
+ public synchronized void scheduleRemapSources(RemapTask data) {
+ if (hasStartedRemap) {
+ throw new UnsupportedOperationException("Cannot add data after remapping has started");
+ }
+
+ this.remapTasks.add(data);
}
- public void remapAll() {
+ public void remapAll() throws IOException {
+ hasStartedRemap = true;
+
if (remapTasks.isEmpty()) {
return;
}
Stopwatch stopwatch = Stopwatch.createStarted();
project.getLogger().lifecycle(":remapping " + remapTasks.size() + " sources");
+ int threads = Math.min(remapTasks.size(), Math.max(2, Runtime.getRuntime().availableProcessors()));
+ ExecutorService ioExecutor = Executors.newFixedThreadPool(2);
+ ExecutorService remapExecutor = Executors.newFixedThreadPool(threads);
- Mercury mercury = getMercuryInstance();
- ThreadingUtils.run(remapTasks, consumer -> consumer.accept(MercuryUtils.copyMercury(mercury)));
+ List<CompletableFuture<Void>> completableFutures = new ArrayList<>();
- project.getLogger().lifecycle(":remapped " + remapTasks.size() + " sources in " + stopwatch.stop());
+ {
+ // We have to build the Mercury instances on the main thread as createMercuryRemapper resolves gradle stuff
+ // TODO refactor this a bit to not do that.
+ var mercuryQueue = new ConcurrentLinkedDeque<Mercury>();
- // TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
- System.gc();
- }
+ final var remapper = createMercuryRemapper();
+ final var inputClasspath = getInputClasspath(project);
- private void remapSourcesInner(Mercury mercury, File source, File destination) throws Exception {
- Stopwatch stopwatch = Stopwatch.createStarted();
- project.getLogger().info(":remapping source jar " + source.getName() + " from " + from + " to " + to);
+ for (int i = 0; i < threads; i++) {
+ Mercury mercury = createMercuryWithClassPath(project, toNamed);
+ mercury.getProcessors().add(remapper);
+ mercury.getClassPath().addAll(inputClasspath);
- if (source.equals(destination)) {
- if (source.isDirectory()) {
- throw new RuntimeException("Directories must differ!");
+ mercuryQueue.add(mercury);
}
- source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
+ ThreadLocal<Mercury> mercuryThreadLocal = ThreadLocal.withInitial(() -> Objects.requireNonNull(mercuryQueue.pop(), "No Mercury instances left"));
+
+ for (RemapTask remapTask : this.remapTasks) {
+ completableFutures.add(
+ CompletableFuture.supplyAsync(() ->
+ prepareForRemap(remapTask), ioExecutor)
+ .thenApplyAsync(remapData -> doRemap(mercuryThreadLocal.get(), remapData), remapExecutor)
+ .thenAcceptAsync(remapData -> completeRemap(remapData, remapTask), ioExecutor)
+ );
+ }
+ }
+ for (CompletableFuture<Void> future : completableFutures) {
try {
- com.google.common.io.Files.move(destination, source);
- } catch (IOException e) {
- throw new RuntimeException("Could not rename " + destination.getName() + "!", e);
+ future.join();
+ } catch (CompletionException e) {
+ try {
+ throw e.getCause();
+ } catch (IOException ioe) {
+ throw ioe;
+ } catch (Throwable unknown) {
+ throw new RuntimeException("An unknown exception occured when remapping", unknown);
+ }
}
}
- Path srcPath = source.toPath();
- boolean isSrcTmp = false;
+ ioExecutor.shutdown();
+ remapExecutor.shutdown();
- if (!source.isDirectory()) {
- // create tmp directory
- isSrcTmp = true;
- srcPath = Files.createTempDirectory("fabric-loom-src");
- ZipUtil.unpack(source, srcPath.toFile());
- }
+ // TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
+ System.gc();
+ }
- if (!destination.isDirectory() && destination.exists()) {
- if (!destination.delete()) {
- throw new RuntimeException("Could not delete " + destination.getName() + "!");
+ private RemapData prepareForRemap(RemapTask remapTask) {
+ try {
+ File source = remapTask.source();
+ final File destination = remapTask.destination();
+
+ if (source.equals(destination)) {
+ if (source.isDirectory()) {
+ throw new RuntimeException("Directories must differ!");
+ }
+
+ source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
+
+ try {
+ com.google.common.io.Files.move(destination, source);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not rename " + destination.getName() + "!", e);
+ }
}
- }
- StitchUtil.FileSystemDelegate dstFs = destination.isDirectory() ? null : StitchUtil.getJarFileSystem(destination, true);
- Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination.toPath();
+ Path srcPath = source.toPath();
+ boolean isSrcTmp = false;
- try {
- mercury.rewrite(srcPath, dstPath);
- } catch (Exception e) {
- project.getLogger().warn("Could not remap " + source.getName() + " fully!", e);
- }
+ if (!source.isDirectory()) {
+ // create tmp directory
+ isSrcTmp = true;
+ srcPath = Files.createTempDirectory("fabric-loom-src");
+ ZipUtil.unpack(source, srcPath.toFile());
+ }
+
+ if (!destination.isDirectory() && destination.exists()) {
+ if (!destination.delete()) {
+ throw new RuntimeException("Could not delete " + destination.getName() + "!");
+ }
+ }
- copyNonJavaFiles(srcPath, dstPath, project, source);
+ StitchUtil.FileSystemDelegate dstFs = remapTask.destination().isDirectory() ? null : StitchUtil.getJarFileSystem(remapTask.destination(), true);
+ Path dstPath = dstFs != null ? dstFs.get().getPath("/") : remapTask.destination().toPath();
- if (dstFs != null) {
- dstFs.close();
+ return new RemapData(Objects.requireNonNull(srcPath, "srcPath"), Objects.requireNonNull(dstPath, "dstPath"), dstFs, isSrcTmp);
+ } catch (IOException e) {
+ throw new CompletionException("Failed to prepare for remap", e);
}
+ }
- if (isSrcTmp) {
- Files.walkFileTree(srcPath, new DeletingFileVisitor());
+ private RemapData doRemap(Mercury mercury, RemapData remapData) {
+ try {
+ mercury.rewrite(remapData.source(), remapData.destination());
+ } catch (Exception e) {
+ project.getLogger().warn("Could not remap " + remapData.source().toString() + " fully!", e);
+ // TODO do something more with this error? delete the dst file in complete remap?
}
- project.getLogger().info(":remapped source jar " + source.getName() + " from " + from + " to " + to + " in " + stopwatch.stop());
+ return remapData;
}
- private Mercury getMercuryInstance() {
- if (this.mercury != null) {
- return this.mercury;
+ private void completeRemap(RemapData remapData, RemapTask remapTask) {
+ try {
+ copyNonJavaFiles(remapData.source(), remapData.destination(), project, remapTask.source());
+
+ if (remapData.dstFs() != null) {
+ remapData.dstFs().close();
+ }
+
+ if (remapData.isSrcTmp()) {
+ Files.walkFileTree(remapData.source(), new DeletingFileVisitor());
+ }
+
+ ZipReprocessorUtil.reprocessZip(remapTask.destination(), remapTask.reproducibleFileOrder(), remapTask.preserveFileTimestamps());
+
+ // Set the remapped sources creation date to match the sources if we're likely succeeded in making it
+ remapTask.destination().setLastModified(remapTask.source().lastModified());
+ } catch (IOException e) {
+ throw new CompletionException("Failed to complete remap", e);
}
+ }
+ private SourceProcessor createMercuryRemapper() {
LoomGradleExtension extension = LoomGradleExtension.get(project);
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
@@ -193,42 +259,7 @@ public class SourceRemapper {
}
});
- Mercury mercury = extension.getOrCreateSrcMercuryCache(id, () -> {
- Mercury m = createMercuryWithClassPath(project, to.equals("named"));
-
- for (File file : extension.getUnmappedModCollection()) {
- Path path = file.toPath();
-
- if (Files.isRegularFile(path)) {
- m.getClassPath().add(path);
- }
- }
-
- m.getClassPath().add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
- m.getClassPath().add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
-
- if (extension.isForge()) {
- m.getClassPath().add(extension.getMinecraftMappedProvider().getSrgJar().toPath());
- m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeMappedJar().toPath());
- m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeIntermediaryJar().toPath());
- m.getClassPath().add(extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
- }
-
- Set<File> files = project.getConfigurations()
- .detachedConfiguration(project.getDependencies().create(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS))
- .resolve();
-
- for (File file : files) {
- m.getClassPath().add(file.toPath());
- }
-
- m.getProcessors().add(MercuryRemapper.create(mappings));
-
- return m;
- });
-
- this.mercury = mercury;
- return mercury;
+ return MercuryRemapper.create(mappings);
}
private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
@@ -246,26 +277,62 @@ public class SourceRemapper {
}
public static Mercury createMercuryWithClassPath(Project project, boolean toNamed) {
- Mercury m = new Mercury();
- m.setGracefulClasspathChecks(true);
+ var mercury = new Mercury();
+ mercury.setGracefulClasspathChecks(true);
+
+ var classpath = mercury.getClassPath();
+ classpath.addAll(getCompileClasspath(project, toNamed));
+
+ return mercury;
+ }
+
+ private static Set<Path> getCompileClasspath(Project project, boolean toNamed) {
+ var classpath = new HashSet<Path>();
for (File file : project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()) {
- m.getClassPath().add(file.toPath());
+ classpath.add(file.toPath());
}
if (!toNamed) {
- for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
- m.getClassPath().add(file.toPath());
+ for (File file : project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).getFiles()) {
+ classpath.add(file.toPath());
}
} else {
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
for (File inputFile : project.getConfigurations().getByName(entry.sourceConfiguration()).getFiles()) {
- m.getClassPath().add(inputFile.toPath());
+ classpath.add(inputFile.toPath());
}
}
}
- return m;
+ return classpath;
+ }
+
+ private static Set<Path> getInputClasspath(Project project) {
+ LoomGradleExtension extension = LoomGradleExtension.get(project);
+
+ var classpath = new HashSet<Path>();
+
+ for (File file : extension.getUnmappedModCollection()) {
+ Path path = file.toPath();
+
+ if (Files.isRegularFile(path)) {
+ classpath.add(path);
+ }
+ }
+
+ classpath.add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
+ classpath.add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
+
+ Set<File> files = project.getConfigurations()
+ .detachedConfiguration(project.getDependencies().create(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS))
+ .resolve();
+
+ for (File file : files) {
+ classpath.add(file.toPath());
+ }
+
+ return classpath;
}
private static boolean isJavaFile(Path path) {
@@ -273,4 +340,10 @@ public class SourceRemapper {
// ".java" is not a valid java file
return name.endsWith(".java") && name.length() != 5;
}
+
+ public static record RemapTask(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
+ }
+
+ public static record RemapData(Path source, Path destination, StitchUtil.FileSystemDelegate dstFs, boolean isSrcTmp) {
+ }
}