mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-02 05:27:43 -05:00
Merge remote-tracking branch 'FabricMC/dev/0.9' into dev/0.9
# Conflicts: # build.gradle # src/main/java/net/fabricmc/loom/LoomGradleExtension.java # src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java # src/main/java/net/fabricmc/loom/build/JarRemapper.java # src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java # src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java # src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java # src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java # src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java # src/main/java/net/fabricmc/loom/task/AbstractRunTask.java # src/main/java/net/fabricmc/loom/task/LoomTasks.java # src/main/java/net/fabricmc/loom/util/Constants.java # src/main/java/net/fabricmc/loom/util/SourceRemapper.java # src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy # src/test/resources/projects/kotlin/build.gradle.kts
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
void setAccessWidener(Object file);
|
||||
RegularFileProperty getAccessWidenerPath();
|
||||
|
||||
void setShareCaches(boolean shareCaches);
|
||||
|
||||
boolean isShareCaches();
|
||||
|
||||
default void shareCaches() {
|
||||
setShareCaches(true);
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default File getAccessWidener() {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("accessWidener", "accessWidenerPath");
|
||||
return getAccessWidenerPath().getAsFile().getOrNull();
|
||||
}
|
||||
|
||||
List<LoomDecompiler> getDecompilers();
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default void setAccessWidener(File file) {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("accessWidener", "accessWidenerPath");
|
||||
getAccessWidenerPath().set(file);
|
||||
}
|
||||
|
||||
void addDecompiler(LoomDecompiler decompiler);
|
||||
Property<Boolean> getShareRemapCaches();
|
||||
|
||||
List<JarProcessor> getJarProcessors();
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default void setShareCaches(boolean shareCaches) {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("shareCaches", "shareRemapCaches");
|
||||
getShareRemapCaches().set(shareCaches);
|
||||
}
|
||||
|
||||
void addJarProcessor(JarProcessor processor);
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default boolean isShareCaches() {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("shareCaches", "shareRemapCaches");
|
||||
return getShareRemapCaches().get();
|
||||
}
|
||||
|
||||
default void shareCaches() {
|
||||
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();
|
||||
}
|
||||
|
||||
default void addDecompiler(LoomDecompiler decompiler) {
|
||||
getGameDecompilers().add(decompiler);
|
||||
}
|
||||
|
||||
ListProperty<JarProcessor> getGameJarProcessors();
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default List<JarProcessor> getJarProcessors() {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("jarProcessors", "gameJarProcessors");
|
||||
return getGameJarProcessors().get();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void setRefmapName(String refmapName);
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default void setRefmapName(String refmapName) {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("refmapName", "mixin.defaultRefmapName");
|
||||
getMixin().getDefaultRefmapName().set(refmapName);
|
||||
}
|
||||
|
||||
boolean isRemapMod();
|
||||
Property<Boolean> getRemapArchives();
|
||||
|
||||
void setRemapMod(boolean remapMod);
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "0.11")
|
||||
default boolean isRemapMod() {
|
||||
getDeprecationHelper().replaceWithInLoom0_11("remapMod", "remapArchives");
|
||||
return getRemapArchives().get();
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
String getCustomManifest();
|
||||
Property<String> getCustomMinecraftManifest();
|
||||
|
||||
@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
|
||||
|
||||
@@ -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}.
|
||||
|
||||
@@ -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);
|
||||
|
||||
outputConsumer.addNonClassFiles(data.input);
|
||||
|
||||
data.processAccessWidener(remapper.getRemapper());
|
||||
remapper.apply(outputConsumer, data.tag);
|
||||
}
|
||||
|
||||
outputConsumers.add(outputConsumer);
|
||||
remapper.finish();
|
||||
} catch (Exception e) {
|
||||
for (RemapData data : remapData) {
|
||||
// Cleanup bad outputs
|
||||
Files.deleteIfExists(data.output);
|
||||
}
|
||||
|
||||
outputConsumer.addNonClassFiles(data.input);
|
||||
|
||||
data.processAccessWidener(remapper.getRemapper());
|
||||
remapper.apply(outputConsumer, data.tag);
|
||||
}
|
||||
|
||||
remapper.finish();
|
||||
|
||||
for (OutputConsumerPath outputConsumer : outputConsumers) {
|
||||
outputConsumer.close();
|
||||
throw new IOException("Failed to remap %s files".formatted(remapData.size()), e);
|
||||
}
|
||||
|
||||
remapData.forEach(RemapData::complete);
|
||||
|
||||
@@ -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();
|
||||
try {
|
||||
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin();
|
||||
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();
|
||||
Collection<String> allMixinConfigs = getMixinConfigurationFiles(readFabricModJson(output));
|
||||
|
||||
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);
|
||||
return mixin.getMixinSourceSetsStream().map(sourceSet -> {
|
||||
MixinApExtension.MixinInformationContainer container = Objects.requireNonNull(
|
||||
MixinApExtension.getMixinInformationContainer(sourceSet)
|
||||
);
|
||||
|
||||
if (!json.has("refmap")) {
|
||||
json.addProperty("refmap", refmapName);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return LoomGradlePlugin.GSON.toJson(json);
|
||||
}
|
||||
})).toArray(ZipEntryTransformerEntry[]::new));
|
||||
}).reduce(false, Boolean::logicalOr);
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,17 +70,23 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -61,11 +61,29 @@ public class GradleMappingContext implements MappingContext {
|
||||
return extension.getMinecraftProvider();
|
||||
}
|
||||
|
||||
@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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,6 +41,8 @@ public interface MappingContext {
|
||||
return minecraftProvider().minecraftVersion();
|
||||
}
|
||||
|
||||
File workingDirectory();
|
||||
|
||||
/**
|
||||
* Creates a temporary working dir to be used to store working files.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,60 +130,45 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getAccessWidener() {
|
||||
public DeprecationHelper getDeprecationHelper() {
|
||||
return deprecationHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegularFileProperty getAccessWidenerPath() {
|
||||
return accessWidener;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@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()) {
|
||||
@@ -196,16 +187,6 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
return refmapName;
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -221,24 +202,13 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
return log4jConfigs;
|
||||
}
|
||||
|
||||
@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;
|
||||
@@ -389,6 +357,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
52
src/main/java/net/fabricmc/loom/util/CloseableList.java
Normal file
52
src/main/java/net/fabricmc/loom/util/CloseableList.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
|
||||
86
src/main/java/net/fabricmc/loom/util/DeprecationHelper.java
Normal file
86
src/main/java/net/fabricmc/loom/util/DeprecationHelper.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
this.scheduleRemapSources(new RemapTask(source, destination, reproducibleFileOrder, preserveFileTimestamps));
|
||||
}
|
||||
|
||||
public void remapAll() {
|
||||
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() 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>();
|
||||
|
||||
final var remapper = createMercuryRemapper();
|
||||
final var inputClasspath = getInputClasspath(project);
|
||||
|
||||
for (int i = 0; i < threads; i++) {
|
||||
Mercury mercury = createMercuryWithClassPath(project, toNamed);
|
||||
mercury.getProcessors().add(remapper);
|
||||
mercury.getClassPath().addAll(inputClasspath);
|
||||
|
||||
mercuryQueue.add(mercury);
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ioExecutor.shutdown();
|
||||
remapExecutor.shutdown();
|
||||
|
||||
// TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
|
||||
System.gc();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Path srcPath = source.toPath();
|
||||
boolean isSrcTmp = false;
|
||||
|
||||
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() + "!");
|
||||
}
|
||||
}
|
||||
|
||||
StitchUtil.FileSystemDelegate dstFs = destination.isDirectory() ? null : StitchUtil.getJarFileSystem(destination, true);
|
||||
Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination.toPath();
|
||||
|
||||
private RemapData prepareForRemap(RemapTask remapTask) {
|
||||
try {
|
||||
mercury.rewrite(srcPath, dstPath);
|
||||
} catch (Exception e) {
|
||||
project.getLogger().warn("Could not remap " + source.getName() + " fully!", e);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Path srcPath = source.toPath();
|
||||
boolean isSrcTmp = false;
|
||||
|
||||
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() + "!");
|
||||
}
|
||||
}
|
||||
|
||||
StitchUtil.FileSystemDelegate dstFs = remapTask.destination().isDirectory() ? null : StitchUtil.getJarFileSystem(remapTask.destination(), true);
|
||||
Path dstPath = dstFs != null ? dstFs.get().getPath("/") : remapTask.destination().toPath();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
copyNonJavaFiles(srcPath, dstPath, project, source);
|
||||
|
||||
if (dstFs != null) {
|
||||
dstFs.close();
|
||||
}
|
||||
|
||||
if (isSrcTmp) {
|
||||
Files.walkFileTree(srcPath, new DeletingFileVisitor());
|
||||
}
|
||||
|
||||
project.getLogger().info(":remapped source jar " + source.getName() + " from " + from + " to " + to + " in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
private Mercury getMercuryInstance() {
|
||||
if (this.mercury != null) {
|
||||
return this.mercury;
|
||||
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?
|
||||
}
|
||||
|
||||
return remapData;
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user