Merge remote-tracking branch 'FabricMC/dev/0.6' into dev/0.6-forge

This commit is contained in:
shedaniel
2021-01-14 17:51:34 +08:00
84 changed files with 1549 additions and 959 deletions

View File

@@ -1,2 +1,4 @@
[*.{gradle,java}]
indent_style = tab
ij_continuation_indent_size = 8
ij_java_imports_layout = $*,|,java.**,|,javax.**,|,*,|,net.fabricmc.**

View File

@@ -3,7 +3,7 @@ name: Java CI
on:
push:
branches:
- 'dev/0.5-forge'
- 'dev/0.6-forge'
jobs:
build:

View File

@@ -4,14 +4,27 @@ Talk to us on [Discord](https://discord.gg/C2RdJDpRBP)!
A fork of [Juuxel's Loom fork]("https://github.com/Juuxel/fabric-loom") that is a fork of [Fabric Loom](https://github.com/FabricMC/fabric-loom) that supports the Forge modding toolchain.
Note that if ForgeGradle works fine for you, *use it*.
This is not meant to be a complete replacement for ForgeGradle,
and there are probably many bugs and limitations here that FG doesn't have.
A [Gradle](https://gradle.org/) plugin to setup a deobfuscated development environment for Minecraft mods. Primarily used in the Fabric toolchain.
* Has built in support for tiny mappings (Used by [Yarn](https://github.com/FabricMC/yarn))
* Utilises the Fernflower and CFR decompilers to generate source code with comments.
* Designed to support modern versions of Minecraft (Tested with 1.14.4 and upwards)
* ~~Built in support for IntelliJ IDEA, Eclipse and Visual Studio Code to generate run configurations for Minecraft.~~
* Loom targets a wide range of Gradle versions. _Tested with 4.9 up to 6.7_
* Supports the latest version of Java all the way down to Java 8
## Usage
Starting with a Fabric project similar to the example mod,
## Use Loom to develop mods
To get started developing your own mods please follow the guide on [Setting up a mod development environment](https://fabricmc.net/wiki/tutorial:setup).
## Debugging Loom (Only needed if you want to work on Loom itself)
_This guide assumes you are using IntelliJ IDEA, other IDE's have not been tested; your experience may vary._
Then you need to set `loom.forge = true` in your `gradle.properties`,
and add the Forge dependency:

View File

@@ -15,7 +15,7 @@ targetCompatibility = 1.8
group = 'me.shedaniel'
archivesBaseName = project.name
def baseVersion = '0.5'
def baseVersion = '0.6'
def build = "release #${System.getenv("GITHUB_RUN_NUMBER") == null ? "custom" : System.getenv("GITHUB_RUN_NUMBER")}"
version = baseVersion + "." + (System.getenv("GITHUB_RUN_NUMBER") == null ? (((short) new Random().nextInt()).abs() + 1000).toString() : System.getenv("GITHUB_RUN_NUMBER"))
@@ -67,7 +67,7 @@ dependencies {
// decompilers
implementation ('net.fabricmc:procyon-fabric-compilertools:0.5.35.13')
implementation ('org.jetbrains:intellij-fernflower:1.2.1.16')
implementation ('net.fabricmc:fabric-fernflower:1.3.0')
implementation ('org.benf:cfr:0.150')
// source code remapping
@@ -96,6 +96,9 @@ dependencies {
testImplementation('org.spockframework:spock-core:1.3-groovy-2.4') {
exclude module: 'groovy-all'
}
compileOnly 'org.jetbrains:annotations:20.1.0'
}
task forgeInjectJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar, dependsOn: [compileForgeInjectJava, processForgeInjectResources]) {

View File

@@ -1,16 +1,5 @@
package net.fabricmc.loom.inject.mixin;
import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ITransformationService;
import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.MixinEnvironment;
import javax.annotation.Nonnull;
import java.io.BufferedReader;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -20,6 +9,19 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nonnull;
import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ITransformationService;
import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.MixinEnvironment;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
public class ForgeLoomMixinRemapperInjectorService implements ITransformationService {
private static final Logger LOGGER = LogManager.getLogger("ForgeLoomRemapperInjector");
@@ -31,12 +33,12 @@ public class ForgeLoomMixinRemapperInjectorService implements ITransformationSer
@Override
public void initialize(IEnvironment environment) {
}
@Override
public void beginScanning(IEnvironment environment) {
LOGGER.debug("We will be injecting our remapper.");
try {
MixinEnvironment.getDefaultEnvironment().getRemappers().add(new MixinIntermediaryDevRemapper(Objects.requireNonNull(resolveMappings()), "intermediary", "named"));
LOGGER.debug("We have successfully injected our remapper.");
@@ -47,7 +49,6 @@ public class ForgeLoomMixinRemapperInjectorService implements ITransformationSer
@Override
public void onLoad(IEnvironment env, Set<String> otherServices) throws IncompatibleEnvironmentException {
}
@Nonnull
@@ -60,6 +61,7 @@ public class ForgeLoomMixinRemapperInjectorService implements ITransformationSer
try {
String srgNamedProperty = System.getProperty("mixin.forgeloom.inject.mappings.srg-named");
Path path = Paths.get(srgNamedProperty);
try (BufferedReader reader = Files.newBufferedReader(path)) {
return TinyMappingFactory.loadWithDetection(reader);
}

View File

@@ -16,13 +16,20 @@
package net.fabricmc.loom.inject.mixin;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.spongepowered.asm.mixin.transformer.ClassInfo;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.Descriptored;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mapping.util.MixinRemapper;
import org.spongepowered.asm.mixin.transformer.ClassInfo;
import java.util.*;
public class MixinIntermediaryDevRemapper extends MixinRemapper {
private static final String ambiguousName = "<ambiguous>"; // dummy value for ambiguous mappings - needs querying with additional owner and/or desc info
@@ -72,6 +79,7 @@ public class MixinIntermediaryDevRemapper extends MixinRemapper {
private String mapMethodNameInner(String owner, String name, String desc) {
String result = super.mapMethodName(owner, name, desc);
if (result.equals(name)) {
String otherClass = unmap(owner);
return super.mapMethodName(otherClass, name, unmapDesc(desc));
@@ -82,6 +90,7 @@ public class MixinIntermediaryDevRemapper extends MixinRemapper {
private String mapFieldNameInner(String owner, String name, String desc) {
String result = super.mapFieldName(owner, name, desc);
if (result.equals(name)) {
String otherClass = unmap(owner);
return super.mapFieldName(otherClass, name, unmapDesc(desc));
@@ -136,12 +145,14 @@ public class MixinIntermediaryDevRemapper extends MixinRemapper {
ClassInfo c = classInfos.remove();
String ownerO = unmap(c.getName());
String s;
if (!(s = mapMethodNameInner(ownerO, name, desc)).equals(name)) {
return s;
}
if (!c.getSuperName().startsWith("java/")) {
ClassInfo cSuper = c.getSuperClass();
if (cSuper != null) {
classInfos.add(cSuper);
}
@@ -153,6 +164,7 @@ public class MixinIntermediaryDevRemapper extends MixinRemapper {
}
ClassInfo cItf = ClassInfo.forName(itf);
if (cItf != null) {
classInfos.add(cItf);
}
@@ -200,6 +212,7 @@ public class MixinIntermediaryDevRemapper extends MixinRemapper {
while (c != null) {
String nextOwner = unmap(c.getName());
String s;
if (!(s = mapFieldNameInner(nextOwner, name, desc)).equals(name)) {
return s;
}

View File

@@ -38,10 +38,7 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.google.gson.JsonObject;
import net.fabricmc.loom.providers.*;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.Project;
@@ -49,13 +46,23 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.plugins.BasePluginConvention;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.processors.JarProcessor;
import net.fabricmc.loom.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.function.LazyBool;
import net.fabricmc.loom.util.LoomDependencyManager;
import net.fabricmc.loom.util.mappings.MojangMappingsDependency;
public class LoomGradleExtension {
private static final String FORGE_PROPERTY = "loom.forge";
@@ -117,32 +124,32 @@ public class LoomGradleExtension {
public Mercury getOrCreateSrcMercuryCache(int id, Supplier<Mercury> factory) {
return srcMercuryCache[id] != null ? srcMercuryCache[id] : (srcMercuryCache[id] = factory.get());
}
public void addTaskBeforeRun(String task) {
synchronized(this.tasksBeforeRun) {
synchronized (this.tasksBeforeRun) {
this.tasksBeforeRun.add(task);
}
}
public List<String> getTasksBeforeRun() {
return tasksBeforeRun;
}
public void silentMojangMappingsLicense() {
this.silentMojangMappingsLicense = true;
}
public boolean isSilentMojangMappingsLicenseEnabled() {
return silentMojangMappingsLicense;
}
public Dependency officialMojangMappings() {
return new MojangMappingsDependency(project, this);
}
public LoomGradleExtension(Project project) {
this.project = project;
this.autoGenIDERuns = AbstractPlugin.isRootProject(project);
this.autoGenIDERuns = isRootProject();
this.unmappedMods = project.files();
this.forge = new LazyBool(() -> Boolean.parseBoolean(Objects.toString(project.findProperty(FORGE_PROPERTY))));
}
@@ -162,8 +169,8 @@ public class LoomGradleExtension {
@Deprecated
public List<Path> getUnmappedMods() {
return unmappedMods.getFiles().stream()
.map(File::toPath)
.collect(Collectors.toList());
.map(File::toPath)
.collect(Collectors.toList());
}
public ConfigurableFileCollection getUnmappedModCollection() {
@@ -263,10 +270,8 @@ public class LoomGradleExtension {
}
public File getNativesDirectory() {
Object customNativesDir = project.getProperties().get("fabric.loom.natives.dir");
if (customNativesDir != null) {
return new File((String) customNativesDir);
if (project.hasProperty("fabric.loom.natives.dir")) {
return new File((String) project.property("fabric.loom.natives.dir"));
}
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().getMinecraftVersion());
@@ -308,7 +313,7 @@ public class LoomGradleExtension {
Project p = this.project;
T result;
while (!AbstractPlugin.isRootProject(p)) {
while (p != p.getRootProject()) {
if ((result = projectTFunction.apply(p)) != null) {
return result;
}
@@ -392,7 +397,7 @@ public class LoomGradleExtension {
public McpConfigProvider getMcpConfigProvider() {
return getDependencyManager().getProvider(McpConfigProvider.class);
}
public SrgProvider getSrgProvider() {
return getDependencyManager().getProvider(SrgProvider.class);
}
@@ -428,11 +433,13 @@ public class LoomGradleExtension {
public String getRefmapName() {
if (refmapName == null || refmapName.isEmpty()) {
String defaultRefmapName;
if (isRootProject()) {
defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
} else {
defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-" + project.getPath().replaceFirst(":", "") + "-refmap.json";
}
project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
refmapName = defaultRefmapName;
}
@@ -473,12 +480,12 @@ public class LoomGradleExtension {
public boolean isForge() {
return forge.getAsBoolean();
}
public boolean shouldGenerateSrgTiny() {
if (generateSrgTiny != null) {
return generateSrgTiny;
}
return isForge();
}
@@ -493,4 +500,8 @@ public class LoomGradleExtension {
public Set<File> getAllMixinMappings() {
return Collections.unmodifiableSet(mixinMappings);
}
public List<LoomDecompiler> getDecompilers() {
return decompilers;
}
}

View File

@@ -24,118 +24,50 @@
package net.fabricmc.loom;
import java.io.File;
import java.util.Locale;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskContainer;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.decompilers.cfr.FabricCFRDecompiler;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.task.CleanEclipseRunsTask;
import net.fabricmc.loom.task.CleanLoomBinaries;
import net.fabricmc.loom.task.CleanLoomMappings;
import net.fabricmc.loom.task.DownloadAssetsTask;
import net.fabricmc.loom.task.GenEclipseRunsTask;
import net.fabricmc.loom.task.GenIdeaProjectTask;
import net.fabricmc.loom.task.GenVsCodeProjectTask;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.task.MigrateMappingsTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.task.RunClientTask;
import net.fabricmc.loom.task.RunServerTask;
import net.fabricmc.loom.configuration.CompileConfiguration;
import net.fabricmc.loom.configuration.FabricApiExtension;
import net.fabricmc.loom.configuration.MavenPublication;
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
import net.fabricmc.loom.task.LoomTasks;
public class LoomGradlePlugin extends AbstractPlugin {
public static File getMappedByproduct(Project project, String suffix) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider();
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {
throw new RuntimeException("Invalid mapped JAR path: " + path);
}
return new File(path.substring(0, path.length() - 4) + suffix);
}
public class LoomGradlePlugin implements Plugin<Project> {
public static boolean refreshDeps;
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
@Override
public void apply(Project target) {
super.apply(target);
public void apply(Project project) {
project.getLogger().lifecycle("Fabric Loom: " + LoomGradlePlugin.class.getPackage().getImplementationVersion());
TaskContainer tasks = target.getTasks();
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();
tasks.register("cleanLoomBinaries", CleanLoomBinaries.class, t -> t.setDescription("Removes binary jars created by Loom."));
tasks.register("cleanLoomMappings", CleanLoomMappings.class, t -> t.setDescription("Removes mappings downloaded by Loom."));
if (refreshDeps) {
MappingsCache.INSTANCE.invalidate();
project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower.");
}
tasks.register("cleanLoom").configure(task -> {
task.setGroup("fabric");
task.setDescription("Runs all Loom cleanup tasks.");
task.dependsOn(tasks.getByName("cleanLoomBinaries"));
task.dependsOn(tasks.getByName("cleanLoomMappings"));
});
// Apply default plugins
project.apply(ImmutableMap.of("plugin", "java"));
project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea"));
tasks.register("migrateMappings", MigrateMappingsTask.class, t -> {
t.setDescription("Migrates mappings to a new version.");
t.getOutputs().upToDateWhen((o) -> false);
});
// Setup extensions, loom shadows minecraft
project.getExtensions().create("minecraft", LoomGradleExtension.class, project);
project.getExtensions().add("loom", project.getExtensions().getByName("minecraft"));
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);
tasks.register("remapJar", RemapJarTask.class, t -> {
t.setDescription("Remaps the built project jar to intermediary mappings.");
t.setGroup("fabric");
});
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric."));
tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> {
t.setDescription("Generates an IntelliJ IDEA workspace from this project.");
t.dependsOn("idea", "downloadAssets");
t.setGroup("ide");
});
tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> {
t.setDescription("Generates Eclipse run configurations for this project.");
t.dependsOn("downloadAssets");
t.setGroup("ide");
});
tasks.register("cleanEclipseRuns", CleanEclipseRunsTask.class, t -> {
t.setDescription("Removes Eclipse run configurations for this project.");
t.setGroup("ide");
});
tasks.register("vscode", GenVsCodeProjectTask.class, t -> {
t.setDescription("Generates VSCode launch configurations.");
t.dependsOn("downloadAssets");
t.setGroup("ide");
});
tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names."));
tasks.register("runClient", RunClientTask.class, t -> {
t.setDescription("Starts a development version of the Minecraft client.");
t.dependsOn("downloadAssets");
t.setGroup("fabric");
});
tasks.register("runServer", RunServerTask.class, t -> {
t.setDescription("Starts a development version of the Minecraft server.");
t.setGroup("fabric");
});
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.addDecompiler(new FabricFernFlowerDecompiler(project));
extension.addDecompiler(new FabricCFRDecompiler(project));
project.afterEvaluate((p) -> {
for (LoomDecompiler decompiler : extension.decompilers) {
String taskName = (decompiler instanceof FabricFernFlowerDecompiler) ? "genSources" : "genSourcesWith" + decompiler.name();
// decompiler will be passed to the constructor of GenerateSourcesTask
tasks.register(taskName, GenerateSourcesTask.class, decompiler);
}
});
CompileConfiguration.setupConfigurations(project);
IdeConfiguration.setup(project);
CompileConfiguration.configureCompile(project);
MavenPublication.configure(project);
LoomTasks.registerTasks(project);
DecompilerConfiguration.setup(project);
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.build;
import java.io.IOException;
import java.nio.file.Path;
@@ -34,8 +34,10 @@ import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import org.gradle.api.Action;
import org.objectweb.asm.commons.Remapper;
import net.fabricmc.loom.util.LoggerFilter;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.InputTag;
@@ -46,6 +48,7 @@ public class JarRemapper {
private final List<IMappingProvider> mappingProviders = new ArrayList<>();
private final Set<Path> classPath = new HashSet<>();
private final List<RemapData> remapData = new ArrayList<>();
private List<Action<TinyRemapper.Builder>> remapOptions;
public void addMappings(IMappingProvider mappingProvider) {
mappingProviders.add(mappingProvider);
@@ -66,6 +69,12 @@ public class JarRemapper {
TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
mappingProviders.forEach(remapperBuilder::withMappings);
if (remapOptions != null) {
for (Action<TinyRemapper.Builder> remapOption : remapOptions) {
remapOption.execute(remapperBuilder);
}
}
TinyRemapper remapper = remapperBuilder.build();
Path[] remapClasspath = classPath.stream()
@@ -103,6 +112,10 @@ public class JarRemapper {
remapData.forEach(RemapData::complete);
}
public void addOptions(List<Action<TinyRemapper.Builder>> remapOptions) {
this.remapOptions = remapOptions;
}
public static class RemapData {
public final Path input;
public final Path output;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.build;
import java.io.File;
import java.io.IOException;
@@ -32,16 +32,14 @@ import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
public final class MixinRefmapHelper {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
import net.fabricmc.loom.LoomGradlePlugin;
public final class MixinRefmapHelper {
private MixinRefmapHelper() { }
public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) {
@@ -52,7 +50,7 @@ public final class MixinRefmapHelper {
return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
@Override
protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class);
JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
if (!json.has("refmap")) {
json.addProperty("refmap", filename);
@@ -62,7 +60,7 @@ public final class MixinRefmapHelper {
json.addProperty("minVersion", mixinVersion);
}
return GSON.toJson(json);
return LoomGradlePlugin.GSON.toJson(json);
}
})).toArray(ZipEntryTransformerEntry[]::new));
} else {
@@ -78,7 +76,7 @@ public final class MixinRefmapHelper {
if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) {
// JSON file in root directory
try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) {
JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class);
JsonObject json = LoomGradlePlugin.GSON.fromJson(inputStreamReader, JsonObject.class);
if (json != null) {
boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray();

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.build;
import java.io.File;
import java.io.IOException;
@@ -45,9 +45,14 @@ import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.processors.dependency.ModDependencyInfo;
import net.fabricmc.loom.processors.dependency.RemapData;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.mods.ModProcessor;
import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
import net.fabricmc.loom.configuration.processors.dependency.RemapData;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.SourceRemapper;
@SuppressWarnings("UnstableApiUsage")
public class ModCompileRemapper {
public static void remapDependencies(Project project, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) {
Logger logger = project.getLogger();
@@ -71,16 +76,13 @@ public class ModCompileRemapper {
String group = artifact.getModuleVersion().getId().getGroup();
String name = artifact.getModuleVersion().getId().getName();
String version = artifact.getModuleVersion().getId().getVersion();
String classifierSuffix = artifact.getClassifier() == null ? "" : (":" + artifact.getClassifier());
if (!shouldRemapMod(logger, artifact, extension.isForge(), sourceConfig.getName())) {
addToRegularCompile(project, regularConfig, artifact);
continue;
}
File sources = findSources(dependencies, artifact);
ModDependencyInfo info = new ModDependencyInfo(group, name, version, classifierSuffix, artifact.getFile(), sources, remappedConfig, remapData);
ModDependencyInfo info = new ModDependencyInfo(group, name, version, artifact.getClassifier(), artifact.getFile(), remappedConfig, remapData);
if (refreshDeps) {
info.forceRemap();
@@ -88,24 +90,32 @@ public class ModCompileRemapper {
modDependencies.add(info);
String remappedLog = group + ":" + name + ":" + version + classifierSuffix + " (" + mappingsSuffix + ")" + (info.requiresRemapping() ? " requires remapping" : " already remapped in " + info.getRemappedOutput().getAbsolutePath());
String remappedLog = group + ":" + name + ":" + version + (artifact.getClassifier() == null ? "" : ":" + artifact.getClassifier()) + " (" + mappingsSuffix + ")" + (info.requiresRemapping() ? " requires remapping" : " already remapped in " + info.getRemappedOutput().getAbsolutePath());
project.getLogger().info(":providing " + remappedLog);
if (sources != null) {
scheduleSourcesRemapping(project, sourceRemapper, info.sourcesFile, info.getRemappedNotation(), info.getRemappedFilename(), modStore);
File remappedSources = info.getRemappedOutput("sources");
if (!remappedSources.exists() || refreshDeps) {
File sources = findSources(dependencies, artifact);
if (sources != null) {
scheduleSourcesRemapping(project, sourceRemapper, sources, info.getRemappedNotation(), remappedSources);
}
}
}
try {
ModProcessor.processMods(project, modDependencies);
} catch (IOException e) {
// Failed to remap, lets clean up to ensure we try again next time
modDependencies.forEach(info -> info.getRemappedOutput().delete());
throw new RuntimeException("Failed to remap mods", e);
}
// Add all of the remapped mods onto the config
for (ModDependencyInfo info : modDependencies) {
project.getLogger().info(":adding " + info.toString() + " into " + info.targetConfig.getName());
project.getDependencies().add(info.targetConfig.getName(), project.getDependencies().module(info.getRemappedNotation()));
project.getDependencies().add(info.targetConfig.getName(), info.getRemappedNotation());
}
}
}
@@ -122,6 +132,7 @@ public class ModCompileRemapper {
logger.info("Found Forge mod in " + config + ": {}", artifact.getId());
return true;
}
logger.lifecycle(":could not find forge mod in " + config + " but forcing: {}", artifact.getId());
return true;
} else {
@@ -151,8 +162,8 @@ public class ModCompileRemapper {
}
public static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) {
@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
.forComponents(artifact.getId().getComponentIdentifier())//
@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()
.forComponents(artifact.getId().getComponentIdentifier())
.withArtifacts(JvmLibrary.class, SourcesArtifact.class);
for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) {
@@ -166,21 +177,13 @@ public class ModCompileRemapper {
return null;
}
private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, File sources, String remappedLog, String remappedFilename, File modStore) {
private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, File sources, String remappedLog, File remappedSources) {
project.getLogger().debug(":providing " + remappedLog + " sources");
File remappedSources = new File(modStore, remappedFilename + "-sources.jar");
boolean refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();
if (!remappedSources.exists() || sources.lastModified() <= 0 || sources.lastModified() > remappedSources.lastModified() || refreshDeps) {
try {
sourceRemapper.scheduleRemapSources(sources, remappedSources);
// Set the remapped sources creation date to match the sources if we're likely succeeded in making it
remappedSources.setLastModified(sources.lastModified());
} catch (Exception e) {
e.printStackTrace();
}
sourceRemapper.scheduleRemapSources(sources, remappedSources, false, true); // Depenedency sources are used in ide only so don't need to be reproducable
} else {
project.getLogger().info(remappedSources.getName() + " is up to date with " + sources.getName());
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.build;
import java.io.File;
import java.io.IOException;
@@ -36,33 +36,31 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.zeroturnaround.zip.FileSource;
import org.zeroturnaround.zip.ZipEntrySource;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.util.Constants;
public class NestedJars {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static boolean addNestedJars(Project project, Path modJarPath) {
List<File> containedJars = getContainedJars(project);
@@ -77,7 +75,7 @@ public class NestedJars {
return ZipUtil.transformEntries(modJar, single(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
@Override
protected String transform(ZipEntry zipEntry, String input) {
JsonObject json = GSON.fromJson(input, JsonObject.class);
JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
JsonArray nestedJars = json.getAsJsonArray("jars");
if (nestedJars == null || !json.has("jars")) {
@@ -92,7 +90,7 @@ public class NestedJars {
json.add("jars", nestedJars);
return GSON.toJson(json);
return LoomGradlePlugin.GSON.toJson(json);
}
})));
}
@@ -228,7 +226,7 @@ public class NestedJars {
custom.addProperty("fabric-loom:generated", true);
jsonObject.add("custom", custom);
return GSON.toJson(jsonObject);
return LoomGradlePlugin.GSON.toJson(jsonObject);
}
private static ZipEntryTransformerEntry[] single(ZipEntryTransformerEntry element) {

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.mixin;
package net.fabricmc.loom.build.mixin;
import java.io.File;
import java.io.IOException;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.mixin;
package net.fabricmc.loom.build.mixin;
import java.io.File;
import java.util.List;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.mixin;
package net.fabricmc.loom.build.mixin;
import java.io.File;
import java.io.IOException;
@@ -35,9 +35,9 @@ import java.util.stream.Collectors;
import kotlin.Unit;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.compile.JavaCompile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin;
import org.jetbrains.kotlin.gradle.plugin.KaptExtension;
import net.fabricmc.loom.LoomGradleExtension;
@@ -92,10 +92,19 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
// Kapt generates an AP configuration for every source set based off of the getKaptConfigurationName method.
return AnnotationProcessorInvoker.getNonTestSourceSets(project)
.map(sourceSet -> project.getConfigurations()
.getByName(Kapt3KotlinGradleSubplugin.Companion.getKaptConfigurationName(sourceSet.getName()))
.getByName(getKaptConfigurationName(sourceSet.getName()))
).collect(Collectors.toList());
}
// Pulled out from the internal class: https://github.com/JetBrains/kotlin/blob/33a0ec9b4f40f3d6f1f96b2db504ade4c2fafe03/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt#L92
private static String getKaptConfigurationName(String sourceSetName) {
if (!sourceSetName.equals(SourceSet.MAIN_SOURCE_SET_NAME)) {
return "kapt" + (sourceSetName.substring(0, 1).toUpperCase() + sourceSetName.substring(1));
}
return "kapt";
}
@Override
protected void passArgument(JavaCompile compileTask, String key, String value) {
// Note: this MUST be run early on, before kapt uses this data, and there is only a point to setting the value once since

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.mixin;
package net.fabricmc.loom.build.mixin;
import java.io.File;

View File

@@ -22,79 +22,59 @@
* SOFTWARE.
*/
package net.fabricmc.loom;
package net.fabricmc.loom.configuration;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import groovy.util.Node;
import net.fabricmc.loom.providers.*;
import net.fabricmc.loom.task.AbstractLoomTask;
import net.fabricmc.loom.task.RemapAllSourcesTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.util.*;
import net.fabricmc.loom.util.mixin.JavaApInvoker;
import net.fabricmc.loom.util.mixin.KaptApInvoker;
import net.fabricmc.loom.util.mixin.ScalaApInvoker;
import org.gradle.api.Plugin;
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.artifacts.Dependency;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.plugins.ide.idea.model.IdeaModel;
import java.io.IOException;
import java.util.*;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.JarRemapper;
import net.fabricmc.loom.build.NestedJars;
import net.fabricmc.loom.build.mixin.JavaApInvoker;
import net.fabricmc.loom.build.mixin.KaptApInvoker;
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
import net.fabricmc.loom.configuration.providers.LaunchProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.task.AbstractLoomTask;
import net.fabricmc.loom.task.RemapAllSourcesTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.SourceRemapper;
public class AbstractPlugin implements Plugin<Project> {
protected Project project;
public static boolean isRootProject(Project project) {
return project.getRootProject() == project;
/**
* Add Minecraft dependencies to compile time.
*/
public final class CompileConfiguration {
private CompileConfiguration() {
}
private void extendsFrom(String a, String b) {
project.getConfigurations().getByName(a).extendsFrom(project.getConfigurations().getByName(b));
}
@Override
public void apply(Project target) {
this.project = target;
project.getLogger().lifecycle("Fabric Loom: " + AbstractPlugin.class.getPackage().getImplementationVersion());
boolean refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();
DownloadUtil.refreshDeps = refreshDeps;
if (refreshDeps) {
MappingsCache.INSTANCE.invalidate();
project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower.");
}
// Apply default plugins
project.apply(ImmutableMap.of("plugin", "java"));
project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea"));
project.getExtensions().create("minecraft", LoomGradleExtension.class, project);
project.getExtensions().add("loom", project.getExtensions().getByName("minecraft"));
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);
public static void setupConfigurations(Project project) {
// Force add Mojang and Forge repositories
addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/");
addMavenRepo(target, "Forge", "https://files.minecraftforge.net/maven/");
addMavenRepo(project, "Mojang", "https://libraries.minecraft.net/");
addMavenRepo(project, "Forge", "https://files.minecraftforge.net/maven/");
Configuration modCompileClasspathConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MOD_COMPILE_CLASSPATH);
modCompileClasspathConfig.setTransitive(true);
@@ -105,6 +85,8 @@ public class AbstractPlugin implements Plugin<Project> {
minecraftNamedConfig.setTransitive(false); // The launchers do not recurse dependencies
Configuration minecraftDependenciesConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MINECRAFT_DEPENDENCIES);
minecraftDependenciesConfig.setTransitive(false);
Configuration loaderDependenciesConfig = project.getConfigurations().maybeCreate(Constants.Configurations.LOADER_DEPENDENCIES);
loaderDependenciesConfig.setTransitive(false);
Configuration minecraftConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MINECRAFT);
minecraftConfig.setTransitive(false);
@@ -129,7 +111,7 @@ public class AbstractPlugin implements Plugin<Project> {
Configuration mcpConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MCP_CONFIG);
mcpConfig.setTransitive(false);
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES);
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
}
Configuration includeConfig = project.getConfigurations().maybeCreate(Constants.Configurations.INCLUDE);
@@ -144,30 +126,23 @@ public class AbstractPlugin implements Plugin<Project> {
Configuration compileModsMappedConfig = project.getConfigurations().maybeCreate(entry.getRemappedConfiguration());
compileModsMappedConfig.setTransitive(false); // Don't get transitive deps of already remapped mods
extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration());
extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration(), project);
if (entry.isOnModCompileClasspath()) {
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration());
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration());
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration(), project);
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration(), project);
}
}
extendsFrom("compileClasspath", Constants.Configurations.MINECRAFT_NAMED);
extendsFrom("runtimeClasspath", Constants.Configurations.MINECRAFT_NAMED);
extendsFrom("testCompileClasspath", Constants.Configurations.MINECRAFT_NAMED);
extendsFrom("testRuntimeClasspath", Constants.Configurations.MINECRAFT_NAMED);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MINECRAFT_NAMED, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MINECRAFT_NAMED, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MINECRAFT_NAMED, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MINECRAFT_NAMED, project);
extendsFrom(Constants.Configurations.MINECRAFT_NAMED, Constants.Configurations.MINECRAFT_DEPENDENCIES);
extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.MINECRAFT_NAMED, Constants.Configurations.LOADER_DEPENDENCIES, project);
extendsFrom("compile", Constants.Configurations.MAPPINGS_FINAL);
configureIDEs();
configureCompile();
configureMaven();
}
public Project getProject() {
return project;
extendsFrom(JavaPlugin.COMPILE_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
}
/**
@@ -178,30 +153,14 @@ public class AbstractPlugin implements Plugin<Project> {
* @param url The URL of the repository
* @return An object containing the name and the URL of the repository that can be modified later
*/
public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) {
public static MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) {
return target.getRepositories().maven(repo -> {
repo.setName(name);
repo.setUrl(url);
});
}
/**
* Add Minecraft dependencies to IDE dependencies.
*/
protected void configureIDEs() {
// IDEA
IdeaModel ideaModel = (IdeaModel) project.getExtensions().getByName("idea");
ideaModel.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles());
ideaModel.getModule().setDownloadJavadoc(true);
ideaModel.getModule().setDownloadSources(true);
ideaModel.getModule().setInheritOutputDirs(true);
}
/**
* Add Minecraft dependencies to compile time.
*/
protected void configureCompile() {
public static void configureCompile(Project project) {
JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
@@ -217,9 +176,9 @@ public class AbstractPlugin implements Plugin<Project> {
flatDirectoryArtifactRepository.setName("UserLocalCacheFiles");
});
project1.getRepositories().flatDir(flatDirectoryArtifactRepository -> {
flatDirectoryArtifactRepository.dir(extension.getRemappedModCache());
flatDirectoryArtifactRepository.setName("UserLocalRemappedMods");
project1.getRepositories().maven(mavenArtifactRepository -> {
mavenArtifactRepository.setUrl(extension.getRemappedModCache());
mavenArtifactRepository.setName("UserLocalRemappedMods");
});
project1.getRepositories().maven(mavenArtifactRepository -> {
@@ -238,30 +197,29 @@ public class AbstractPlugin implements Plugin<Project> {
});
project1.getRepositories().mavenCentral();
project1.getRepositories().jcenter();
LoomDependencyManager dependencyManager = new LoomDependencyManager();
extension.setDependencyManager(dependencyManager);
dependencyManager.addProvider(new MinecraftProvider(getProject()));
dependencyManager.addProvider(new MinecraftProvider(project));
if (extension.isForge()) {
dependencyManager.addProvider(new ForgeProvider(getProject()));
dependencyManager.addProvider(new ForgeUserdevProvider(getProject()));
dependencyManager.addProvider(new ForgeProvider(project));
dependencyManager.addProvider(new ForgeUserdevProvider(project));
}
if (extension.shouldGenerateSrgTiny()) {
dependencyManager.addProvider(new SrgProvider(getProject()));
dependencyManager.addProvider(new SrgProvider(project));
}
if (extension.isForge()) {
dependencyManager.addProvider(new McpConfigProvider(getProject()));
dependencyManager.addProvider(new PatchProvider(getProject()));
dependencyManager.addProvider(new ForgeUniversalProvider(getProject()));
dependencyManager.addProvider(new McpConfigProvider(project));
dependencyManager.addProvider(new PatchProvider(project));
dependencyManager.addProvider(new ForgeUniversalProvider(project));
}
dependencyManager.addProvider(new MappingsProvider(getProject()));
dependencyManager.addProvider(new LaunchProvider(getProject()));
dependencyManager.addProvider(new MappingsProvider(project));
dependencyManager.addProvider(new LaunchProvider(project));
dependencyManager.handleDependencies(project1);
@@ -290,12 +248,15 @@ public class AbstractPlugin implements Plugin<Project> {
remapJarTask.getToM().set("srg");
((Jar) jarTask).manifest(manifest -> {
List<String> configs = new ArrayList<>();
if (extension.mixinConfig != null) {
configs.add(extension.mixinConfig);
}
if (extension.mixinConfigs != null) {
configs.addAll(extension.mixinConfigs);
}
manifest.attributes(ImmutableMap.of("MixinConfigs", String.join(",", configs)));
});
}
@@ -308,18 +269,11 @@ public class AbstractPlugin implements Plugin<Project> {
remapJarTask.dependsOn(jarTask);
project1.getTasks().getByName("build").dependsOn(remapJarTask);
Map<Project, Set<Task>> taskMap = project.getAllTasks(true);
for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) {
Set<Task> taskSet = entry.getValue();
for (Task task : taskSet) {
if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) {
//Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects
NestedJars.getRequiredTasks(project1).forEach(task::dependsOn);
}
project.getTasks().withType(RemapJarTask.class).forEach(task -> {
if (task.getAddNestedDependencies().getOrElse(false)) {
NestedJars.getRequiredTasks(project1).forEach(task::dependsOn);
}
}
});
SourceRemapper remapper = null;
Task parentTask = project1.getTasks().getByName("build");
@@ -407,66 +361,7 @@ public class AbstractPlugin implements Plugin<Project> {
}
}
protected void configureMaven() {
project.afterEvaluate((p) -> {
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
if (!entry.hasMavenScope()) {
continue;
}
Configuration compileModsConfig = p.getConfigurations().getByName(entry.getSourceConfiguration());
// add modsCompile to maven-publish
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish != null) {
mavenPublish.publications((publications) -> {
for (Publication publication : publications) {
if (publication instanceof MavenPublication) {
((MavenPublication) publication).pom((pom) -> pom.withXml((xml) -> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>();
GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> {
Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId");
if (groupId.isPresent() && artifactId.isPresent()) {
foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text());
}
});
for (Dependency dependency : compileModsConfig.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {
continue;
}
Node depNode = dependencies.appendNode("dependency");
depNode.appendNode("groupId", dependency.getGroup());
depNode.appendNode("artifactId", dependency.getName());
depNode.appendNode("version", dependency.getVersion());
depNode.appendNode("scope", entry.getMavenScope());
if (dependency instanceof ModuleDependency) {
final Set<ExcludeRule> exclusions = ((ModuleDependency) dependency).getExcludeRules();
if (!exclusions.isEmpty()) {
Node exclusionsNode = depNode.appendNode("exclusions");
for (ExcludeRule rule : exclusions) {
Node exclusionNode = exclusionsNode.appendNode("exclusion");
exclusionNode.appendNode("groupId", rule.getGroup() == null ? "*" : rule.getGroup());
exclusionNode.appendNode("artifactId", rule.getModule() == null ? "*" : rule.getModule());
}
}
}
}
}));
}
}
});
}
}
});
private static void extendsFrom(String a, String b, Project project) {
project.getConfigurations().getByName(a).extendsFrom(project.getConfigurations().getByName(b));
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration;
import java.io.File;
import java.nio.charset.StandardCharsets;
@@ -100,6 +100,8 @@ public abstract class DependencyProvider {
final Dependency dependency;
final Configuration sourceConfiguration;
private String resolvedVersion = null;
public static DependencyInfo create(Project project, Dependency dependency, Configuration sourceConfiguration) {
if (dependency instanceof SelfResolvingDependency) {
return new FileDependencyInfo(project, (SelfResolvingDependency) dependency, sourceConfiguration);
@@ -119,13 +121,19 @@ public abstract class DependencyProvider {
}
public String getResolvedVersion() {
if (resolvedVersion != null) {
return resolvedVersion;
}
for (ResolvedDependency rd : sourceConfiguration.getResolvedConfiguration().getFirstLevelModuleDependencies()) {
if (rd.getModuleGroup().equals(dependency.getGroup()) && rd.getModuleName().equals(dependency.getName())) {
return rd.getModuleVersion();
resolvedVersion = rd.getModuleVersion();
return resolvedVersion;
}
}
return dependency.getVersion();
resolvedVersion = dependency.getVersion();
return resolvedVersion;
}
public Configuration getSourceConfiguration() {

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration;
import java.io.File;
import java.io.IOException;
@@ -40,6 +40,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DownloadUtil;
public class FabricApiExtension {
private final Project project;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration;
import java.io.File;
import java.util.ArrayList;
@@ -39,8 +39,12 @@ import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.DependencyProvider.DependencyInfo;
import net.fabricmc.loom.build.ModCompileRemapper;
import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo;
import net.fabricmc.loom.configuration.mods.ModProcessor;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.SourceRemapper;
public class LoomDependencyManager {
private static class ProviderList {
@@ -54,7 +58,7 @@ public class LoomDependencyManager {
private final List<DependencyProvider> dependencyProviderList = new ArrayList<>();
public void addProvider(DependencyProvider provider) {
public <T extends DependencyProvider> T addProvider(T provider) {
if (dependencyProviderList.contains(provider)) {
throw new RuntimeException("Provider is already registered");
}
@@ -65,6 +69,7 @@ public class LoomDependencyManager {
provider.register(this);
dependencyProviderList.add(provider);
return provider;
}
public <T> T getProvider(Class<T> clazz) {
@@ -82,7 +87,7 @@ public class LoomDependencyManager {
MappingsProvider mappingsProvider = null;
project.getLogger().lifecycle(":setting up loom dependencies");
project.getLogger().info(":setting up loom dependencies");
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
Map<String, ProviderList> providerListMap = new HashMap<>();
List<ProviderList> targetProviders = new ArrayList<>();
@@ -133,9 +138,7 @@ public class LoomDependencyManager {
SourceRemapper sourceRemapper = new SourceRemapper(project, true);
String platformSuffix = extension.isForge() ? "_forge" : "";
String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + platformSuffix + "." + mappingsProvider.mappingsVersion;
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, sourceRemapper);
String mappingsKey = mappingsProvider.getMappingsKey();
if (extension.getInstallerJson() == null) {
//If we've not found the installer JSON we've probably skipped remapping Fabric loader, let's go looking
@@ -153,16 +156,17 @@ public class LoomDependencyManager {
project.getLogger().info("Found installer JSON in " + input);
extension.setInstallerJson(jsonObject);
handleInstallerJson(extension.getInstallerJson(), project);
}
}
}
if (extension.getInstallerJson() != null) {
handleInstallerJson(extension.getInstallerJson(), project);
} else if (!extension.isForge()) {
if (extension.getInstallerJson() == null && !extension.isForge()) {
project.getLogger().warn("fabric-installer.json not found in classpath!");
}
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, sourceRemapper);
sourceRemapper.remapAll();
for (Runnable runnable : afterTasks) {
@@ -174,7 +178,7 @@ public class LoomDependencyManager {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
JsonObject libraries = jsonObject.get("libraries").getAsJsonObject();
Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES);
Configuration loaderDepsConfig = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES);
Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor");
libraries.get("common").getAsJsonArray().forEach(jsonElement -> {
@@ -182,7 +186,7 @@ public class LoomDependencyManager {
ExternalModuleDependency modDep = (ExternalModuleDependency) project.getDependencies().create(name);
modDep.setTransitive(false);
mcDepsConfig.getDependencies().add(modDep);
loaderDepsConfig.getDependencies().add(modDep);
if (!extension.ideSync()) {
apDepsConfig.getDependencies().add(modDep);

View File

@@ -0,0 +1,119 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.configuration;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import groovy.util.Node;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.GroovyXmlUtil;
public final class MavenPublication {
private MavenPublication() {
}
public static void configure(Project project) {
project.afterEvaluate((p) -> {
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
if (!entry.hasMavenScope()) {
continue;
}
Configuration compileModsConfig = p.getConfigurations().getByName(entry.getSourceConfiguration());
// add modsCompile to maven-publish
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish != null) {
processEntry(entry, compileModsConfig, mavenPublish);
}
}
});
}
private static void processEntry(RemappedConfigurationEntry entry, Configuration compileModsConfig, PublishingExtension mavenPublish) {
mavenPublish.publications((publications) -> {
for (Publication publication : publications) {
if (!(publication instanceof org.gradle.api.publish.maven.MavenPublication)) {
continue;
}
((org.gradle.api.publish.maven.MavenPublication) publication).pom((pom) -> pom.withXml((xml) -> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>();
GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> {
Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId");
if (groupId.isPresent() && artifactId.isPresent()) {
foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text());
}
});
for (Dependency dependency : compileModsConfig.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {
continue;
}
Node depNode = dependencies.appendNode("dependency");
depNode.appendNode("groupId", dependency.getGroup());
depNode.appendNode("artifactId", dependency.getName());
depNode.appendNode("version", dependency.getVersion());
depNode.appendNode("scope", entry.getMavenScope());
if (!(dependency instanceof ModuleDependency)) {
continue;
}
final Set<ExcludeRule> exclusions = ((ModuleDependency) dependency).getExcludeRules();
if (exclusions.isEmpty()) {
continue;
}
Node exclusionsNode = depNode.appendNode("exclusions");
for (ExcludeRule rule : exclusions) {
Node exclusionNode = exclusionsNode.appendNode("exclusion");
exclusionNode.appendNode("groupId", rule.getGroup() == null ? "*" : rule.getGroup());
exclusionNode.appendNode("artifactId", rule.getModule() == null ? "*" : rule.getModule());
}
}
}));
}
});
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration;
import org.gradle.api.artifacts.ConfigurationContainer;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.accesswidener;
package net.fabricmc.loom.configuration.accesswidener;
import java.io.BufferedReader;
import java.io.File;
@@ -48,14 +48,14 @@ import org.zeroturnaround.zip.transform.ZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import net.fabricmc.accesswidener.AccessWidener;
import net.fabricmc.accesswidener.AccessWidenerRemapper;
import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerRemapper;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.accesswidener.AccessWidenerWriter;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.processors.JarProcessor;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.tinyremapper.TinyRemapper;
public class AccessWidenerJarProcessor implements JarProcessor {

View File

@@ -22,40 +22,21 @@
* SOFTWARE.
*/
package net.fabricmc.loom.task;
package net.fabricmc.loom.configuration.ide;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftPatchedProvider;
import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.Project;
import org.gradle.plugins.ide.idea.model.IdeaModel;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
public final class IdeConfiguration {
private IdeConfiguration() {
}
public class CleanLoomBinaries extends AbstractLoomTask {
@TaskAction
public void run() {
LoomGradleExtension extension = getExtension();
extension.getMinecraftProvider().getMergedJar().delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
Optional.ofNullable(extension.getMinecraftMappedProvider().getSrgJar()).ifPresent(File::delete);
if (extension.isForge()) {
try {
MinecraftPatchedProvider provider = new MinecraftPatchedProvider(extension.getMappingsProvider(), getProject());
provider.initFiles();
provider.cleanAllCache();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void setup(Project project) {
IdeaModel ideaModel = (IdeaModel) project.getExtensions().getByName("idea");
try {
FileUtils.deleteDirectory(extension.getNativesDirectory());
FileUtils.deleteDirectory(extension.getNativesJarStore());
} catch (IOException e) {
e.printStackTrace();
}
ideaModel.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles());
ideaModel.getModule().setDownloadJavadoc(true);
ideaModel.getModule().setDownloadSources(true);
ideaModel.getModule().setInheritOutputDirs(true);
}
}

View File

@@ -22,14 +22,26 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration.ide;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
@@ -40,16 +52,9 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static net.fabricmc.loom.AbstractPlugin.isRootProject;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
public class RunConfig {
public String configName;
@@ -85,11 +90,12 @@ public class RunConfig {
this.addXml(envs, "env", ImmutableMap.of("name", envEntry.getKey(), "value", envEntry.getValue()));
}
}
if (!tasksBeforeRun.isEmpty()) {
Element methodElement = this.addXml(root, "method", ImmutableMap.of("v", "2"));
this.addXml(methodElement, "option", ImmutableMap.of("name", "Make", "enabled", "true"));
for (String s : tasksBeforeRun) {
String project = s.substring(0, s.lastIndexOf(':'));
String task = s.substring(s.lastIndexOf(':') + 1);
@@ -103,7 +109,7 @@ public class RunConfig {
.build());
}
}
return root;
}
@@ -135,7 +141,7 @@ public class RunConfig {
}
private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) {
runConfig.configName += isRootProject(project) ? "" : " (" + project.getPath() + ")";
runConfig.configName += extension.isRootProject() ? "" : " (" + project.getPath() + ")";
runConfig.eclipseProjectName = project.getExtensions().getByType(EclipseModel.class).getProject().getName();
runConfig.ideaModuleName = getIdeaModuleName(project);
runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir;
@@ -143,10 +149,9 @@ public class RunConfig {
if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) {
runConfig.mainClass = "net.minecraft.launchwrapper.Launch";
runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.LaunchWrapper.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.LaunchWrapper.DEFAULT_FABRIC_SERVER_TWEAKER);
runConfig.programArgs += "--tweakClass " + ("client".equals(mode) ? Constants.LaunchWrapper.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.LaunchWrapper.DEFAULT_FABRIC_SERVER_TWEAKER);
} else {
runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main";
runConfig.programArgs = "";
runConfig.vmArgs = "-Dfabric.dli.config=" + encodeEscaped(extension.getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + mode.toLowerCase();
}
@@ -198,6 +203,7 @@ public class RunConfig {
RunConfig ideaClient = new RunConfig();
ideaClient.configName = "Minecraft Client";
ideaClient.programArgs = "";
populate(project, extension, ideaClient, "client");
ideaClient.vmArgs += getOSClientJVMArgs();
ideaClient.vmArgs += " -Dfabric.dli.main=" + getMainClass("client", extension);
@@ -211,6 +217,7 @@ public class RunConfig {
RunConfig ideaServer = new RunConfig();
ideaServer.configName = "Minecraft Server";
ideaServer.programArgs = "nogui ";
populate(project, extension, ideaServer, "server");
ideaServer.vmArgs += " -Dfabric.dli.main=" + getMainClass("server", extension);
ideaServer.tasksBeforeRun = new ArrayList<>(extension.getTasksBeforeRun());
@@ -256,13 +263,15 @@ public class RunConfig {
}
dummyConfig = dummyConfig.replace("%ENVS%", envs);
StringBuilder tasksToRun = new StringBuilder();
for (String s : tasksBeforeRun) {
String project = s.substring(0, s.lastIndexOf(':'));
String task = s.substring(s.lastIndexOf(':') + 1);
tasksToRun.append(" <option name=\"Gradle.BeforeRunTask\" enabled=\"true\" tasks=\"").append(task).append("\" externalProjectPath=\"").append(project).append("\" vmOptions=\"\" scriptParameters=\"\" />");
}
dummyConfig = dummyConfig.replace("%TASKS%", tasksToRun.toString());
return dummyConfig;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration.ide;
import java.io.File;
import java.io.IOException;
@@ -32,8 +32,8 @@ import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftNativesProvider;
import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider;
public class SetupIntelijRunConfigs {
public static void setup(Project project) {

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration.mods;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
@@ -31,21 +31,20 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
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.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
@@ -59,19 +58,22 @@ import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerRemapper;
import net.fabricmc.accesswidener.AccessWidenerWriter;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.processors.dependency.ModDependencyInfo;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.LoggerFilter;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.srg.AtRemapper;
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.InputTag;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class ModProcessor {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static void processMods(Project project, List<ModDependencyInfo> processList) throws IOException {
if (processList.stream().noneMatch(ModDependencyInfo::requiresRemapping)) {
return;
@@ -108,9 +110,9 @@ public class ModProcessor {
ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
@Override
protected String transform(ZipEntry zipEntry, String input) {
JsonObject json = GSON.fromJson(input, JsonObject.class);
JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class);
json.remove("jars");
return GSON.toJson(json);
return LoomGradlePlugin.GSON.toJson(json);
}
}))});
}
@@ -143,7 +145,8 @@ public class ModProcessor {
MappingsProvider mappingsProvider = extension.getMappingsProvider();
Path mc = extension.isForge() ? mappedProvider.getSrgJar().toPath() : mappedProvider.getIntermediaryJar().toPath();
Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()
.stream().map(File::toPath).toArray(Path[]::new);
List<ModDependencyInfo> remapList = processList.stream().filter(ModDependencyInfo::requiresRemapping).collect(Collectors.toList());
@@ -152,9 +155,9 @@ public class ModProcessor {
TinyTree mappings = extension.isForge() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings();
LoggerFilter.replaceSystemOut();
TinyRemapper remapper = TinyRemapper.newRemapper()
.withMappings(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false))
.renameInvalidLocals(false)
.build();
.withMappings(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false))
.renameInvalidLocals(false)
.build();
remapper.readClassPathAsync(mc);
remapper.readClassPathAsync(mcDeps);
@@ -209,7 +212,7 @@ public class ModProcessor {
if (extension.isForge()) {
AtRemapper.remap(project.getLogger(), info.getRemappedOutput().toPath(), mappings);
CoreModClassRemapper.remapJar(info.getRemappedOutput().toPath(), mappings, project.getLogger());
if (ZipUtil.containsEntry(info.getRemappedOutput(), "META-INF/MANIFEST.MF")) {
ZipUtil.transformEntry(info.getRemappedOutput(), "META-INF/MANIFEST.MF", (in, zipEntry, out) -> {
Manifest manifest = new Manifest(in);
@@ -219,7 +222,7 @@ public class ModProcessor {
out.closeEntry();
});
}
List<String> filesToRemove = new ArrayList<>();
ZipUtil.iterate(info.getRemappedOutput(), (in, zipEntry) -> {
if (zipEntry.getName().toLowerCase(Locale.ROOT).endsWith(".rsa") || zipEntry.getName().toLowerCase(Locale.ROOT).endsWith(".sf")) {
@@ -230,12 +233,14 @@ public class ModProcessor {
});
ZipUtil.removeEntries(info.getRemappedOutput(), filesToRemove.toArray(new String[0]));
}
info.finaliseRemapping();
}
}
private static void fixManifest(Manifest manifest) {
Attributes mainAttrs = manifest.getMainAttributes();
mainAttrs.remove(Attributes.Name.SIGNATURE_VERSION);
for (Iterator<Attributes> it = manifest.getEntries().values().iterator(); it.hasNext(); ) {
@@ -254,7 +259,7 @@ public class ModProcessor {
}
}
static JsonObject readInstallerJson(File file, Project project) {
public static JsonObject readInstallerJson(File file, Project project) {
try {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
String launchMethod = extension.getLoaderLaunchMethod();
@@ -285,7 +290,7 @@ public class ModProcessor {
}
}
return GSON.fromJson(jsonStr, JsonObject.class);
return LoomGradlePlugin.GSON.fromJson(jsonStr, JsonObject.class);
} catch (IOException e) {
e.printStackTrace();
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.processors;
package net.fabricmc.loom.configuration.processors;
import java.io.File;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.processors;
package net.fabricmc.loom.configuration.processors;
import java.io.File;
import java.util.List;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.processors;
package net.fabricmc.loom.configuration.processors;
import java.io.File;
import java.io.IOException;
@@ -31,9 +31,9 @@ import java.util.function.Consumer;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Constants;
public class MinecraftProcessedProvider extends MinecraftMappedProvider {
@@ -51,7 +51,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
@Override
protected void addDependencies(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) {
boolean isForgeAtDirty = getExtension().isForge() && getExtension().getMappingsProvider().patchedProvider.isAtDirty();
if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps() || isForgeAtDirty) {
getProject().getLogger().lifecycle(":processing mapped jar");
invalidateJars();

View File

@@ -22,54 +22,85 @@
* SOFTWARE.
*/
package net.fabricmc.loom.processors.dependency;
package net.fabricmc.loom.configuration.processors.dependency;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.gradle.api.artifacts.Configuration;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.util.ModProcessor;
import net.fabricmc.loom.LoomGradlePlugin;
public class ModDependencyInfo {
public final String group;
private final String group;
public final String name;
public final String version;
@Nullable
public final String classifier;
public final File inputFile;
public final File sourcesFile;
public final Configuration targetConfig;
public final RemapData remapData;
private boolean forceRemap = false;
public ModDependencyInfo(String group, String name, String version, String classifier, File inputFile, File sourcesFile, Configuration targetConfig, RemapData remapData) {
public ModDependencyInfo(String group, String name, String version, @Nullable String classifier, File inputFile, Configuration targetConfig, RemapData remapData) {
this.group = group;
this.name = name;
this.version = version;
this.classifier = classifier;
this.inputFile = inputFile;
this.sourcesFile = sourcesFile;
this.targetConfig = targetConfig;
this.remapData = remapData;
}
public String getRemappedNotation() {
return String.format("%s:%s:%s@%s%s", group, name, version, remapData.mappingsSuffix, classifier);
if (!hasClassifier()) {
return String.format("%s:%s:%s", getGroup(), name, version);
}
return String.format("%s:%s:%s:%s", getGroup(), name, version, classifier);
}
public String getRemappedFilename() {
return String.format("%s-%s@%s", name, version, remapData.mappingsSuffix + classifier.replace(':', '-'));
public String getRemappedFilename(boolean withClassifier) {
if (!hasClassifier() || !withClassifier) {
return String.format("%s-%s", name, version);
}
return String.format("%s-%s-%s", name, version, classifier);
}
public File getRemappedDir() {
return new File(remapData.modStore, String.format("%s/%s/%s", getGroup().replace(".", "/"), name, version));
}
public File getRemappedOutput() {
return new File(remapData.modStore, getRemappedFilename() + ".jar");
return new File(getRemappedDir(), getRemappedFilename(true) + ".jar");
}
public File getRemappedOutput(String classifier) {
return new File(getRemappedDir(), getRemappedFilename(false) + "-" + classifier + ".jar");
}
private File getRemappedPom() {
return new File(getRemappedDir(), String.format("%s-%s", name, version) + ".pom");
}
private String getGroup() {
return getMappingsPrefix(remapData.mappingsSuffix) + "." + group;
}
public static String getMappingsPrefix(String mappings) {
return mappings.replace(".", "_").replace("-", "_").replace("+", "_");
}
public File getInputFile() {
@@ -77,11 +108,31 @@ public class ModDependencyInfo {
}
public boolean requiresRemapping() {
return !getRemappedOutput().exists() || inputFile.lastModified() <= 0 || inputFile.lastModified() > getRemappedOutput().lastModified() || forceRemap;
return !getRemappedOutput().exists() || inputFile.lastModified() <= 0 || inputFile.lastModified() > getRemappedOutput().lastModified() || forceRemap || !getRemappedPom().exists();
}
public void finaliseRemapping() {
getRemappedOutput().setLastModified(inputFile.lastModified());
savePom();
}
private void savePom() {
try {
String pomTemplate;
try (InputStream input = ModDependencyInfo.class.getClassLoader().getResourceAsStream("mod_compile_template.pom")) {
pomTemplate = IOUtils.toString(input, StandardCharsets.UTF_8);
}
pomTemplate = pomTemplate
.replace("%GROUP%", getGroup())
.replace("%NAME%", name)
.replace("%VERSION%", version);
FileUtils.writeStringToFile(getRemappedPom(), pomTemplate, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Failed to write mod pom", e);
}
}
public void forceRemap() {
@@ -90,7 +141,11 @@ public class ModDependencyInfo {
@Override
public String toString() {
return String.format("%s:%s:%s:%s", group, name, version, classifier);
return getRemappedNotation();
}
public boolean hasClassifier() {
return classifier != null && !classifier.isEmpty();
}
public String getAccessWidener() throws IOException {
@@ -102,7 +157,7 @@ public class ModDependencyInfo {
}
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
JsonObject json = ModProcessor.GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
JsonObject json = LoomGradlePlugin.GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
if (!json.has("accessWidener")) {
return null;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.processors.dependency;
package net.fabricmc.loom.configuration.processors.dependency;
import java.io.File;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers;
import java.io.File;
import java.io.IOException;
@@ -42,9 +42,9 @@ import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.RemappedConfigurationEntry;
public class LaunchProvider extends DependencyProvider {
public Dependency annotationDependency;
@@ -82,9 +82,9 @@ public class LaunchProvider extends DependencyProvider {
.argument("server", "--launchTarget")
.argument("server", "fmluserdevserver")
.property("mixin.env.remapRefMap", "true");
if (getExtension().useFabricMixin) {
launchConfig.property("mixin.forgeloom.inject.mappings.srg-named", getExtension().getMappingsProvider().mixinTinyMappingsWithSrg.getAbsolutePath());
} else {
@@ -98,6 +98,7 @@ public class LaunchProvider extends DependencyProvider {
launchConfig.argument("-mixin.config");
launchConfig.argument(mixinConfig);
}
if (mixinConfigs != null) {
for (String config : mixinConfigs) {
launchConfig.argument("-mixin.config");
@@ -146,7 +147,7 @@ public class LaunchProvider extends DependencyProvider {
private void writeRemapClassPath() {
List<String> inputConfigurations = new ArrayList<>();
inputConfigurations.add(Constants.Configurations.MINECRAFT_DEPENDENCIES);
inputConfigurations.add(Constants.Configurations.LOADER_DEPENDENCIES);
inputConfigurations.addAll(Constants.MOD_COMPILE_ENTRIES.stream().map(RemappedConfigurationEntry::getSourceConfiguration).collect(Collectors.toList()));
List<File> remapClasspath = new ArrayList<>();

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers;
import java.io.File;
import java.io.FileReader;
@@ -31,6 +31,8 @@ import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipError;
import com.google.common.io.Files;
@@ -40,12 +42,14 @@ import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.ManifestVersion;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import net.fabricmc.loom.util.StaticPathWatcher;
import net.fabricmc.loom.util.HashedDownloadUtil;
import net.fabricmc.stitch.merge.JarMerger;
public class MinecraftProvider extends DependencyProvider {
@@ -55,9 +59,10 @@ public class MinecraftProvider extends DependencyProvider {
private MinecraftLibraryProvider libraryProvider;
private File minecraftJson;
File minecraftClientJar;
File minecraftServerJar;
public File minecraftClientJar;
public File minecraftServerJar;
private File minecraftMergedJar;
private File versionManifestJson;
private String jarSuffix = "";
Gson gson = new Gson();
@@ -69,7 +74,7 @@ public class MinecraftProvider extends DependencyProvider {
@Override
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
minecraftVersion = dependency.getDependency().getVersion();
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForge()) {
addDependency("de.oceanlabs.mcp:mcp_config:" + minecraftVersion, Constants.Configurations.SRG);
}
@@ -81,7 +86,7 @@ public class MinecraftProvider extends DependencyProvider {
downloadMcJson(offline);
try (FileReader reader = new FileReader(minecraftJson)) {
versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class);
versionInfo = LoomGradlePlugin.GSON.fromJson(reader, MinecraftVersionInfo.class);
}
// Add Loom as an annotation processor
@@ -121,29 +126,30 @@ public class MinecraftProvider extends DependencyProvider {
minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json");
}
private void downloadMcJson(boolean offline) throws IOException {
File manifests = new File(getExtension().getUserCache(), "version_manifest.json");
if (getExtension().isShareCaches() && !getExtension().isRootProject() && manifests.exists() && !isRefreshDeps()) {
if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) {
return;
}
if (offline) {
if (manifests.exists()) {
if (!offline && !isRefreshDeps() && hasRecentValidManifest()) {
// We have a recent valid manifest file, so do nothing
} else if (offline) {
if (versionManifestJson.exists()) {
// If there is the manifests already we'll presume that's good enough
getProject().getLogger().debug("Found version manifests, presuming up-to-date");
} else {
// If we don't have the manifests then there's nothing more we can do
throw new GradleException("Version manifests not found at " + manifests.getAbsolutePath());
throw new GradleException("Version manifests not found at " + versionManifestJson.getAbsolutePath());
}
} else {
getProject().getLogger().debug("Downloading version manifests");
DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), manifests, getProject().getLogger());
DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), versionManifestJson, getProject().getLogger());
}
String versionManifest = Files.asCharSource(manifests, StandardCharsets.UTF_8).read();
String versionManifest = Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read();
ManifestVersion mcManifest = new GsonBuilder().create().fromJson(versionManifest, ManifestVersion.class);
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
@@ -170,9 +176,18 @@ public class MinecraftProvider extends DependencyProvider {
throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + minecraftJson.getAbsolutePath());
}
} else {
if (StaticPathWatcher.INSTANCE.hasFileChanged(minecraftJson.toPath()) || isRefreshDeps()) {
getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion);
DownloadUtil.downloadIfChanged(new URL(optionalVersion.get().url), minecraftJson, getProject().getLogger());
getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion);
String url = optionalVersion.get().url;
// Find the sha1 of the json from the url, return true if it matches the local json
Pattern sha1Pattern = Pattern.compile("\\b[0-9a-f]{5,40}\\b");
Matcher matcher = sha1Pattern.matcher(url);
if (matcher.find()) {
HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, matcher.group(), getProject().getLogger(), true);
} else {
// Use the etag if no hash found from url
DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger());
}
}
} else {
@@ -180,13 +195,37 @@ public class MinecraftProvider extends DependencyProvider {
}
}
private boolean hasRecentValidManifest() throws IOException {
if (getExtension().customManifest != null) {
return false;
}
if (!versionManifestJson.exists() || !minecraftJson.exists()) {
return false;
}
if (versionManifestJson.lastModified() > System.currentTimeMillis() - 24 * 3_600_000) {
// Version manifest hasn't been modified in 24 hours, time to get a new one.
return false;
}
ManifestVersion manifest = new GsonBuilder().create().fromJson(Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(), ManifestVersion.class);
Optional<ManifestVersion.Versions> version = manifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
// fail if the expected mc version was not found, will download the file again.
return version.isPresent();
}
private void downloadJars(Logger logger) throws IOException {
if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) {
return;
}
DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("client").url), minecraftClientJar, logger);
DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("server").url), minecraftServerJar, logger);
MinecraftVersionInfo.Downloads client = versionInfo.downloads.get("client");
MinecraftVersionInfo.Downloads server = versionInfo.downloads.get("server");
HashedDownloadUtil.downloadIfInvalid(new URL(client.url), minecraftClientJar, client.sha1, logger, false);
HashedDownloadUtil.downloadIfInvalid(new URL(server.url), minecraftServerJar, server.sha1, logger, false);
}
private void mergeJars(Logger logger) throws IOException {
@@ -218,7 +257,7 @@ public class MinecraftProvider extends DependencyProvider {
return jarSuffix;
}
void setJarSuffix(String jarSuffix) {
public void setJarSuffix(String jarSuffix) {
this.jarSuffix = jarSuffix;
}

View File

@@ -22,14 +22,14 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.forge;
import java.util.function.Consumer;
import org.gradle.api.Project;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
public class ForgeProvider extends DependencyProvider {
private ForgeVersion version = new ForgeVersion(null);

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
import java.util.function.Consumer;
@@ -30,8 +30,8 @@ import java.util.function.Consumer;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.JarUtil;
public class ForgeUniversalProvider extends DependencyProvider {

View File

@@ -22,21 +22,26 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
import java.io.Reader;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import org.gradle.api.Project;
import java.io.File;
import java.io.Reader;
import java.net.URI;
import java.nio.file.*;
import java.util.function.Consumer;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
public class ForgeUserdevProvider extends DependencyProvider {
private File userdevJar;

View File

@@ -22,11 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import org.gradle.api.Project;
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
import java.nio.file.Files;
@@ -34,6 +30,11 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import org.gradle.api.Project;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
public class McpConfigProvider extends DependencyProvider {
private File mcp;

View File

@@ -22,19 +22,38 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.forge;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonParser;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import net.fabricmc.loom.util.*;
import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.minecraftforge.accesstransformer.AccessTransformerEngine;
import net.minecraftforge.accesstransformer.TransformerProcessor;
import net.minecraftforge.accesstransformer.parser.AccessTransformerList;
@@ -53,21 +72,22 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.zeroturnaround.zip.ZipUtil;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.JarUtil;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class MinecraftPatchedProvider extends DependencyProvider {
private final MappingsProvider mappingsProvider;
@@ -128,6 +148,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
PatchProvider patchProvider = getExtension().getPatchProvider();
String minecraftVersion = minecraftProvider.getMinecraftVersion();
String jarSuffix = "-patched-forge-" + patchProvider.forgeVersion;
if (getExtension().useFabricMixin) {
jarSuffix += "-fabric-mixin";
}
@@ -158,11 +179,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
for (File file : getGlobalCaches()) {
file.delete();
}
cleanProjectCache();
}
private File[] getGlobalCaches() {
return new File[]{
return new File[] {
minecraftClientSrgJar,
minecraftServerSrgJar,
minecraftClientPatchedSrgJar,
@@ -177,7 +199,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private File[] getProjectCache() {
return new File[]{
return new File[] {
minecraftClientPatchedSrgATJar,
minecraftServerPatchedSrgATJar,
minecraftClientPatchedOfficialJar,
@@ -238,6 +260,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider();
String[] mappingsPath = {null};
if (!ZipUtil.handle(mcpProvider.getMcp(), "config.json", (in, zipEntry) -> {
mappingsPath[0] = new JsonParser().parse(new InputStreamReader(in)).getAsJsonObject().get("data").getAsJsonObject().get("mappings").getAsString();
})) {
@@ -245,8 +268,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
Path[] tmpSrg = {null};
if (!ZipUtil.handle(mcpProvider.getMcp(), mappingsPath[0], (in, zipEntry) -> {
tmpSrg[0] = Files.createTempFile(null, null);
try (BufferedWriter writer = Files.newBufferedWriter(tmpSrg[0])) {
IOUtils.copy(in, writer, StandardCharsets.UTF_8);
}
@@ -260,12 +285,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
ThreadingUtils.run(() -> {
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
}, () -> {
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
});
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
});
}
private void fixParameterAnnotation(File jarFile) throws Exception {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.toString());
try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + jarFile.toURI()), ImmutableMap.of("create", false))) {
for (Path rootDir : fs.getRootDirectories()) {
for (Path file : (Iterable<? extends Path>) Files.walk(rootDir)::iterator) {
@@ -279,6 +305,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
node.accept(writer);
byte[] out = writer.toByteArray();
if (!Arrays.equals(bytes, out)) {
Files.delete(file);
Files.write(file, out);
@@ -309,6 +336,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
if (it.getFileName().toString().equals("MANIFEST.MF")) {
return false;
}
return getExtension().useFabricMixin || !it.getFileName().toString().endsWith("cpw.mods.modlauncher.api.ITransformationService");
}, this::copyReplacing);
}
@@ -326,7 +354,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
target.delete();
File at = File.createTempFile("at" + side, ".cfg");
JarUtil.extractFile(inputCopied, "META-INF/accesstransformer.cfg", at);
String[] args = new String[]{
String[] args = new String[] {
"--inJar", inputCopied.getAbsolutePath(),
"--outJar", target.getAbsolutePath(),
"--atFile", at.getAbsolutePath()
@@ -387,12 +415,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void remapPatchedJars(Logger logger) throws Exception {
Path[] libraries = getExtension()
.getMinecraftProvider()
.getLibraryProvider()
.getLibraries()
.stream()
.map(File::toPath)
Path[] libraries = getProject().getConfigurations()
.getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES)
.getFiles()
.stream().map(File::toPath)
.toArray(Path[]::new);
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
@@ -424,13 +450,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
});
}
private void patchJars(Logger logger) throws IOException {
logger.lifecycle(":patching jars");
PatchProvider patchProvider = getExtension().getPatchProvider();
patchJars(minecraftClientSrgJar, minecraftClientPatchedSrgJar, patchProvider.clientPatches);
patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches);
ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> {
copyMissingClasses(environment.srgJar.apply(this), environment.patchedSrgJar.apply(this));
fixParameterAnnotation(environment.patchedSrgJar.apply(this));
@@ -439,18 +465,23 @@ public class MinecraftPatchedProvider extends DependencyProvider {
private void patchJars(File clean, File output, Path patches) throws IOException {
PrintStream previous = System.out;
try {
System.setOut(new PrintStream(new NullOutputStream()));
} catch (SecurityException ignored) {
// Failed to replace logger filter, just ignore
}
ConsoleTool.main(new String[]{
ConsoleTool.main(new String[] {
"--clean", clean.getAbsolutePath(),
"--output", output.getAbsolutePath(),
"--apply", patches.toAbsolutePath().toString()
});
try {
System.setOut(previous);
} catch (SecurityException ignored) {
// Failed to replace logger filter, just ignore
}
}
@@ -469,7 +500,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action)
throws IOException {
try (FileSystemUtil.FileSystemDelegate sourceFs = FileSystemUtil.getJarFileSystem(source, false);
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
for (Path sourceDir : toWalk.apply(sourceFs.get())) {
Path dir = sourceDir.toAbsolutePath();
Files.walk(dir)

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.forge;
import java.net.URI;
import java.nio.file.FileSystem;
@@ -35,8 +35,8 @@ import java.util.function.Consumer;
import com.google.common.collect.ImmutableMap;
import org.gradle.api.Project;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
public class PatchProvider extends DependencyProvider {
public Path clientPatches;

View File

@@ -22,18 +22,23 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import org.gradle.api.Project;
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
import java.net.URI;
import java.nio.file.*;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableMap;
import org.gradle.api.Project;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
public class SrgProvider extends DependencyProvider {
private File srg;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.IOException;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
@@ -40,7 +40,6 @@ import java.util.function.Consumer;
import com.google.common.base.Preconditions;
import com.google.common.net.UrlEscapers;
import net.fabricmc.loom.util.srg.SrgNamedWriter;
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.util.StringUtils;
import org.gradle.api.Project;
@@ -49,14 +48,18 @@ import org.zeroturnaround.zip.ZipEntrySource;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.processors.JarProcessorManager;
import net.fabricmc.loom.processors.MinecraftProcessedProvider;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.forge.MinecraftPatchedProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.srg.SrgMerger;
import net.fabricmc.loom.util.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.util.srg.SrgNamedWriter;
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.Command;
@@ -112,7 +115,7 @@ public class MappingsProvider extends DependencyProvider {
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class);
getProject().getLogger().lifecycle(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
getProject().getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
String version = dependency.getResolvedVersion();
File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency));
@@ -120,6 +123,8 @@ public class MappingsProvider extends DependencyProvider {
this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
this.minecraftVersion = minecraftProvider.getMinecraftVersion();
boolean isV2;
// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings
if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) {
String yarnVersion = dependency.getDependency().getVersion();
@@ -129,9 +134,13 @@ public class MappingsProvider extends DependencyProvider {
if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) {
throw new RuntimeException(String.format("Minecraft Version (%s) does not match yarn's minecraft version (%s)", minecraftVersion, yarnMinecraftVersion));
}
// We can save reading the zip file + header by checking the file name
isV2 = mappingsJar.getName().endsWith("-v2.jar");
} else {
isV2 = doesJarContainV2Mappings(mappingsJar.toPath());
}
boolean isV2 = doesJarContainV2Mappings(mappingsJar.toPath());
this.mappingsVersion = version + (isV2 ? "-v2" : "");
initFiles();
@@ -163,25 +172,25 @@ public class MappingsProvider extends DependencyProvider {
if (!tinyMappingsJar.exists() || isRefreshDeps()) {
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
}
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
}
}
if (getExtension().isForge()) {
if (!getExtension().shouldGenerateSrgTiny()) {
throw new IllegalStateException("We have to generate srg tiny in a forge environment!");
}
if (!mixinTinyMappingsWithSrg.exists() || isRefreshDeps()) {
List<String> lines = new ArrayList<>(Files.readAllLines(tinyMappingsWithSrg));
lines.set(0, lines.get(0).replace("intermediary", "yraidemretni").replace("srg", "intermediary"));
Files.deleteIfExists(mixinTinyMappingsWithSrg.toPath());
Files.write(mixinTinyMappingsWithSrg.toPath(), lines);
}
if (!srgToNamedSrg.exists() || isRefreshDeps()) {
SrgNamedWriter.writeTo(getProject().getLogger(), srgToNamedSrg.toPath(), getMappingsWithSrg(), "srg", "named");
}
@@ -379,4 +388,8 @@ public class MappingsProvider extends DependencyProvider {
return intermediaryTiny;
}
public String getMappingsKey() {
return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion;
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.mappings;
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
@@ -47,18 +47,25 @@ import org.cadixdev.lorenz.model.MethodMapping;
import org.cadixdev.lorenz.model.TopLevelClassMapping;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.*;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.ModuleIdentifier;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.MutableVersionConstraint;
import org.gradle.api.artifacts.SelfResolvingDependency;
import org.gradle.api.artifacts.VersionConstraint;
import org.gradle.api.internal.artifacts.DefaultModuleIdentifier;
import org.gradle.api.internal.artifacts.ModuleVersionSelectorStrictSpec;
import org.gradle.api.internal.artifacts.dependencies.*;
import org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependency;
import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint;
import org.gradle.api.tasks.TaskDependency;
import org.zeroturnaround.zip.ByteSource;
import org.zeroturnaround.zip.ZipEntrySource;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyMappingFactory;
@@ -80,7 +87,7 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement
this.project = project;
this.extension = extension;
}
@Override
public ExternalModuleDependency copy() {
MojangMappingsDependency copiedProjectDependency = new MojangMappingsDependency(project, extension);
@@ -90,26 +97,25 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement
@Override
public void version(Action<? super MutableVersionConstraint> action) {
}
@Override
public boolean isForce() {
return this.force;
}
@Override
public ExternalModuleDependency setForce(boolean force) {
this.validateMutation(this.force, force);
this.force = force;
return this;
}
@Override
public boolean isChanging() {
return this.changing;
}
@Override
public ExternalModuleDependency setChanging(boolean changing) {
this.validateMutation(this.changing, changing);
@@ -150,11 +156,11 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement
project.getLogger().warn("Please make sure to read and understand the following license:");
project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String line;
while ((line = clientBufferedReader.readLine()).startsWith("#")) {
project.getLogger().warn(line);
}
project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
} catch (IOException e) {
throw new RuntimeException("Failed to read client mappings", e);
@@ -204,7 +210,7 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement
ClassMapping<?, ?> mojangClassMapping = intermediaryToMojang.getOrCreateClassMapping(inputMappings.getFullObfuscatedName())
.setDeobfuscatedName(namedClass.getFullDeobfuscatedName());
for (FieldMapping fieldMapping : inputMappings .getFieldMappings()) {
for (FieldMapping fieldMapping : inputMappings.getFieldMappings()) {
namedClass.getFieldMapping(fieldMapping.getDeobfuscatedName())
.ifPresent(namedField -> {
mojangClassMapping.getOrCreateFieldMapping(fieldMapping.getSignature())
@@ -212,7 +218,7 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement
});
}
for (MethodMapping methodMapping : inputMappings .getMethodMappings()) {
for (MethodMapping methodMapping : inputMappings.getMethodMappings()) {
namedClass.getMethodMapping(methodMapping.getDeobfuscatedSignature())
.ifPresent(namedMethod -> {
mojangClassMapping.getOrCreateMethodMapping(methodMapping.getSignature())

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration.providers.minecraft;
import java.util.ArrayList;
import java.util.List;

View File

@@ -22,23 +22,19 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.MinecraftVersionInfo;
public class MinecraftLibraryProvider {
public File MINECRAFT_LIBS;
private final Collection<File> libs = new HashSet<>();
public void provide(MinecraftProvider minecraftProvider, Project project) {
MinecraftVersionInfo versionInfo = minecraftProvider.getVersionInfo();
@@ -60,10 +56,6 @@ public class MinecraftLibraryProvider {
}
}
public Collection<File> getLibraries() {
return libs;
}
private void initFiles(Project project, MinecraftProvider minecraftProvider) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries");

View File

@@ -22,11 +22,33 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import com.google.common.collect.ImmutableMap;
import org.gradle.api.Project;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.srg.AtRemapper;
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
@@ -35,22 +57,6 @@ import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.NonClassCopyMode;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import org.gradle.api.Project;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
public class MinecraftMappedProvider extends DependencyProvider {
private static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>()
@@ -92,7 +98,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
if (minecraftIntermediaryJar.exists()) {
minecraftIntermediaryJar.delete();
}
if (getExtension().isForge() && minecraftSrgJar.exists()) {
minecraftSrgJar.delete();
}
@@ -103,9 +109,11 @@ public class MinecraftMappedProvider extends DependencyProvider {
// Cleanup some some things that may be in a bad state now
minecraftMappedJar.delete();
minecraftIntermediaryJar.delete();
if (getExtension().isForge()) {
minecraftSrgJar.delete();
}
getExtension().getMappingsProvider().cleanFiles();
throw new RuntimeException("Failed to remap minecraft", t);
}
@@ -128,78 +136,65 @@ public class MinecraftMappedProvider extends DependencyProvider {
Path outputIntermediary = minecraftIntermediaryJar.toPath();
Path outputSrg = minecraftSrgJar == null ? null : minecraftSrgJar.toPath();
ExecutorService executor = Executors.newFixedThreadPool(Math.min(10, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1)));
List<Future<?>> futures = new LinkedList<>();
ThreadingUtils.run(getExtension().isForge() ? Arrays.asList("named", "intermediary", "srg") : Arrays.asList("named", "intermediary"), toM -> {
Path output = "named".equals(toM) ? outputMapped : "srg".equals(toM) ? outputSrg : outputIntermediary;
for (String toM : (getExtension().isForge() ? Arrays.asList("named", "intermediary", "srg") : Arrays.asList("named", "intermediary"))) {
futures.add(executor.submit(() -> {
try {
Path output = "named".equals(toM) ? outputMapped : "srg".equals(toM) ? outputSrg : outputIntermediary;
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
TinyRemapper remapper = getTinyRemapper(input, fromM, toM);
TinyRemapper remapper = getTinyRemapper(input, fromM, toM);
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
if (getExtension().isForge()) {
outputConsumer.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, remapper);
} else {
outputConsumer.addNonClassFiles(input);
}
remapper.readClassPath(getRemapClasspath());
remapper.readInputs(input);
remapper.apply(outputConsumer);
} catch (Exception e) {
Files.deleteIfExists(output);
throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
} finally {
remapper.finish();
}
if (getExtension().isForge() && !"srg".equals(toM)) {
getProject().getLogger().info(":running forge finalising tasks");
// TODO: Relocate this to its own class
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + output.toUri()), ImmutableMap.of("create", false))) {
Path manifestPath = fs.getPath("META-INF", "MANIFEST.MF");
Manifest minecraftManifest;
Manifest forgeManifest;
try (InputStream in = Files.newInputStream(manifestPath)) {
minecraftManifest = new Manifest(in);
}
try (InputStream in = new FileInputStream(getExtension().getForgeUniversalProvider().getForgeManifest())) {
forgeManifest = new Manifest(in);
}
for (Map.Entry<String, Attributes> forgeEntry : forgeManifest.getEntries().entrySet()) {
if (forgeEntry.getKey().endsWith("/")) {
minecraftManifest.getEntries().put(forgeEntry.getKey(), forgeEntry.getValue());
}
}
Files.delete(manifestPath);
try (OutputStream out = Files.newOutputStream(manifestPath)) {
minecraftManifest.write(out);
}
}
TinyTree yarnWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
AtRemapper.remap(getProject().getLogger(), output, yarnWithSrg);
CoreModClassRemapper.remapJar(output, yarnWithSrg, getProject().getLogger());
}
} catch (IOException e) {
throw new RuntimeException(e);
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
if (getExtension().isForge()) {
outputConsumer.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, remapper);
} else {
outputConsumer.addNonClassFiles(input);
}
}));
}
for (Future<?> future : futures) {
future.get();
}
remapper.readClassPath(getRemapClasspath());
remapper.readInputs(input);
remapper.apply(outputConsumer);
} catch (Exception e) {
Files.deleteIfExists(output);
throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
} finally {
remapper.finish();
}
if (getExtension().isForge() && !"srg".equals(toM)) {
getProject().getLogger().info(":running forge finalising tasks");
// TODO: Relocate this to its own class
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + output.toUri()), ImmutableMap.of("create", false))) {
Path manifestPath = fs.getPath("META-INF", "MANIFEST.MF");
Manifest minecraftManifest;
Manifest forgeManifest;
try (InputStream in = Files.newInputStream(manifestPath)) {
minecraftManifest = new Manifest(in);
}
try (InputStream in = new FileInputStream(getExtension().getForgeUniversalProvider().getForgeManifest())) {
forgeManifest = new Manifest(in);
}
for (Map.Entry<String, Attributes> forgeEntry : forgeManifest.getEntries().entrySet()) {
if (forgeEntry.getKey().endsWith("/")) {
minecraftManifest.getEntries().put(forgeEntry.getKey(), forgeEntry.getValue());
}
}
Files.delete(manifestPath);
try (OutputStream out = Files.newOutputStream(manifestPath)) {
minecraftManifest.write(out);
}
}
TinyTree yarnWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg();
AtRemapper.remap(getProject().getLogger(), output, yarnWithSrg);
CoreModClassRemapper.remapJar(output, yarnWithSrg, getProject().getLogger());
}
});
}
public TinyRemapper getTinyRemapper(@Nullable Path fromJar, String fromM, String toM) throws IOException {
@@ -214,6 +209,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
* They won't get remapped to their proper packages, so IllegalAccessErrors will happen without ._.
*/
builder.fixPackageAccess(true);
if (fromJar != null) {
builder.withMappings(InnerClassRemapper.of(fromJar, getExtension().getMappingsProvider().getMappingsWithSrg(), fromM, toM));
}
@@ -225,7 +221,8 @@ public class MinecraftMappedProvider extends DependencyProvider {
}
public Path[] getRemapClasspath() {
return getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
return getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
.stream().map(File::toPath).toArray(Path[]::new);
}
protected void addDependencies(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) {
@@ -251,14 +248,10 @@ public class MinecraftMappedProvider extends DependencyProvider {
return String.format("%s-%s-%s-%s%s", minecraftProvider.getMinecraftVersion(), type, getExtension().getMappingsProvider().mappingsName, getExtension().getMappingsProvider().mappingsVersion, minecraftProvider.getJarSuffix());
}
public Collection<File> getMapperPaths() {
return minecraftProvider.getLibraryProvider().getLibraries();
}
public File getIntermediaryJar() {
return minecraftIntermediaryJar;
}
public File getSrgJar() {
return minecraftSrgJar;
}

View File

@@ -22,19 +22,19 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.gradle.api.GradleException;
import org.zeroturnaround.zip.ZipUtil;
import org.gradle.api.Project;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.MinecraftVersionInfo;
public class MinecraftNativesProvider {
public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File;
import java.util.List;
@@ -31,6 +31,9 @@ import java.util.Map;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
public class MinecraftVersionInfo {
public List<Library> libraries;
public Map<String, Downloads> downloads;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.assets;
package net.fabricmc.loom.configuration.providers.minecraft.assets;
import java.util.HashSet;
import java.util.LinkedHashMap;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.assets;
package net.fabricmc.loom.configuration.providers.minecraft.assets;
@SuppressWarnings("unused")
public class AssetObject {

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.providers;
package net.fabricmc.loom.configuration.providers.minecraft.assets;
import java.io.File;
import java.io.FileReader;
@@ -40,13 +40,12 @@ import org.gradle.api.GradleException;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import net.fabricmc.loom.util.assets.AssetIndex;
import net.fabricmc.loom.util.assets.AssetObject;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.loom.util.gradle.ProgressLogger;
public class MinecraftAssetsProvider {
public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {

View File

@@ -22,28 +22,21 @@
* SOFTWARE.
*/
package net.fabricmc.loom.task;
package net.fabricmc.loom.decompilers;
import java.io.IOException;
import java.nio.file.Files;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.decompilers.cfr.FabricCFRDecompiler;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
public class CleanLoomMappings extends AbstractLoomTask {
@TaskAction
public void run() {
try {
LoomGradleExtension extension = getExtension();
extension.getMappingsProvider().clean();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor());
getExtension().getMappingsProvider().cleanFiles();
} catch (IOException e) {
throw new RuntimeException(e);
}
public final class DecompilerConfiguration {
private DecompilerConfiguration() {
}
public static void setup(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.addDecompiler(new FabricFernFlowerDecompiler(project));
extension.addDecompiler(new FabricCFRDecompiler(project));
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.decompilers;
import static java.text.MessageFormat.format;
@@ -46,7 +46,8 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.gradle.ProgressLogger;
/**
* TODO, Move to stitch.

View File

@@ -99,46 +99,48 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler {
Map<String, ProgressLogger> inUseLoggers = new HashMap<>();
progressGroup.started();
ExecResult result = ForkingJavaExec.javaexec(project.getRootProject(), spec -> {
spec.setMain(fernFlowerExecutor().getName());
spec.jvmArgs("-Xms200m", "-Xmx3G");
spec.setArgs(args);
spec.setErrorOutput(System.err);
spec.setStandardOutput(new ConsumingOutputStream(line -> {
if (line.startsWith("Listening for transport") || !line.contains("::")) {
System.out.println(line);
return;
}
int sepIdx = line.indexOf("::");
String id = line.substring(0, sepIdx).trim();
String data = line.substring(sepIdx + 2).trim();
ProgressLogger logger = inUseLoggers.get(id);
String[] segs = data.split(" ");
if (segs[0].equals("waiting")) {
if (logger != null) {
logger.progress("Idle..");
inUseLoggers.remove(id);
freeLoggers.push(logger);
}
} else {
if (logger == null) {
if (!freeLoggers.isEmpty()) {
logger = freeLoggers.pop();
} else {
logger = loggerFactory.get();
ExecResult result = ForkingJavaExec.javaexec(
project.getRootProject().getPlugins().hasPlugin("fabric-loom") ? project.getRootProject() : project,
spec -> {
spec.setMain(fernFlowerExecutor().getName());
spec.jvmArgs("-Xms200m", "-Xmx3G");
spec.setArgs(args);
spec.setErrorOutput(System.err);
spec.setStandardOutput(new ConsumingOutputStream(line -> {
if (line.startsWith("Listening for transport") || !line.contains("::")) {
System.out.println(line);
return;
}
inUseLoggers.put(id, logger);
}
int sepIdx = line.indexOf("::");
String id = line.substring(0, sepIdx).trim();
String data = line.substring(sepIdx + 2).trim();
logger.progress(data);
}
}));
});
ProgressLogger logger = inUseLoggers.get(id);
String[] segs = data.split(" ");
if (segs[0].equals("waiting")) {
if (logger != null) {
logger.progress("Idle..");
inUseLoggers.remove(id);
freeLoggers.push(logger);
}
} else {
if (logger == null) {
if (!freeLoggers.isEmpty()) {
logger = freeLoggers.pop();
} else {
logger = loggerFactory.get();
}
inUseLoggers.put(id, logger);
}
logger.progress(data);
}
}));
});
inUseLoggers.values().forEach(ProgressLogger::completed);
freeLoggers.forEach(ProgressLogger::completed);
progressGroup.completed();

View File

@@ -35,7 +35,7 @@ import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
public abstract class AbstractRunTask extends JavaExec {
private final Function<Project, RunConfig> configProvider;
@@ -45,9 +45,6 @@ public abstract class AbstractRunTask extends JavaExec {
super();
setGroup("fabric");
this.configProvider = config;
classpath(getProject().getConfigurations().getByName("runtimeClasspath"));
classpath(this.getProject().getExtensions().getByType(LoomGradleExtension.class).getUnmappedModCollection());
}
@Override
@@ -56,6 +53,9 @@ public abstract class AbstractRunTask extends JavaExec {
config = configProvider.apply(getProject());
}
classpath(getProject().getConfigurations().getByName("runtimeClasspath"));
classpath(this.getProject().getExtensions().getByType(LoomGradleExtension.class).getUnmappedModCollection());
List<String> argsSplit = new ArrayList<>();
String[] args = config.programArgs.split(" ");
int partPos = -1;

View File

@@ -30,8 +30,8 @@ import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftNativesProvider;
import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider;
public class DownloadAssetsTask extends AbstractLoomTask {
@TaskAction

View File

@@ -32,7 +32,7 @@ import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
public class GenEclipseRunsTask extends AbstractLoomTask {
@TaskAction

View File

@@ -37,28 +37,28 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.AbstractPlugin;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
public class GenIdeaProjectTask extends AbstractLoomTask {
@TaskAction
public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException {
Project project = this.getProject();
LoomGradleExtension extension = getExtension();
// Only generate the idea runs on the root project
if (!AbstractPlugin.isRootProject(project)) {
if (!extension.isRootProject()) {
return;
}
LoomGradleExtension extension = getExtension();
project.getLogger().lifecycle(":Building idea workspace");
File file = project.file(project.getName() + ".iws");

View File

@@ -37,7 +37,7 @@ import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
// Recommended vscode plugins:
// https://marketplace.visualstudio.com/items?itemName=redhat.java

View File

@@ -30,17 +30,20 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.Locale;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.util.LineNumberRemapper;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.decompilers.LineNumberRemapper;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.gradle.ProgressLogger;
import net.fabricmc.stitch.util.StitchUtil;
public class GenerateSourcesTask extends AbstractLoomTask {
@@ -58,23 +61,23 @@ public class GenerateSourcesTask extends AbstractLoomTask {
public void doTask() throws Throwable {
int threads = Runtime.getRuntime().availableProcessors();
Path javaDocs = getExtension().getMappingsProvider().tinyMappings.toPath();
Collection<Path> libraries = getExtension().getMinecraftProvider().getLibraryProvider().getLibraries()
Collection<Path> libraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
.stream().map(File::toPath).collect(Collectors.toSet());
DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries);
Path compiledJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath();
Path sourcesDestination = LoomGradlePlugin.getMappedByproduct(getProject(), "-sources.jar").toPath();
Path linemap = LoomGradlePlugin.getMappedByproduct(getProject(), "-sources.lmap").toPath();
Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath();
Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath();
decompiler.decompile(compiledJar, sourcesDestination, linemap, metadata);
if (Files.exists(linemap)) {
Path linemappedJarDestination = LoomGradlePlugin.getMappedByproduct(getProject(), "-linemapped.jar").toPath();
Path linemappedJarDestination = getMappedJarFileWithSuffix("-linemapped.jar").toPath();
remapLineNumbers(compiledJar, linemap, linemappedJarDestination);
// In order for IDEs to recognize the new line mappings, we need to overwrite the existing compiled jar
// with the linemapped one. In the name of not destroying the existing jar, we will copy it to somewhere else.
Path unlinemappedJar = LoomGradlePlugin.getMappedByproduct(getProject(), "-unlinemapped.jar").toPath();
Path unlinemappedJar = getMappedJarFileWithSuffix("-unlinemapped.jar").toPath();
// The second time genSources is ran, we want to keep the existing unlinemapped jar.
if (!Files.exists(unlinemappedJar)) {
@@ -91,7 +94,7 @@ public class GenerateSourcesTask extends AbstractLoomTask {
LineNumberRemapper remapper = new LineNumberRemapper();
remapper.readMappings(linemap.toFile());
ProgressLogger progressLogger = net.fabricmc.loom.util.progress.ProgressLogger.getProgressFactory(getProject(), getClass().getName());
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName());
progressLogger.start("Adjusting line numbers", "linemap");
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(oldCompiledJar.toFile(), true);
@@ -101,4 +104,17 @@ public class GenerateSourcesTask extends AbstractLoomTask {
progressLogger.completed();
}
private File getMappedJarFileWithSuffix(String suffix) {
LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider();
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {
throw new RuntimeException("Invalid mapped JAR path: " + path);
}
return new File(path.substring(0, path.length() - 4) + suffix);
}
}

View File

@@ -0,0 +1,108 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016, 2017, 2018 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.task;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskContainer;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
public final class LoomTasks {
private LoomTasks() {
}
public static void registerTasks(Project project) {
TaskContainer tasks = project.getTasks();
tasks.register("migrateMappings", MigrateMappingsTask.class, t -> {
t.setDescription("Migrates mappings to a new version.");
t.getOutputs().upToDateWhen((o) -> false);
});
tasks.register("remapJar", RemapJarTask.class, t -> {
t.setDescription("Remaps the built project jar to intermediary mappings.");
t.setGroup("fabric");
});
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric."));
tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names."));
registerIDETasks(tasks);
registerRunTasks(tasks);
registerDecompileTasks(tasks, project);
}
private static void registerIDETasks(TaskContainer tasks) {
tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> {
t.setDescription("Generates an IntelliJ IDEA workspace from this project.");
t.dependsOn("idea", "downloadAssets");
t.setGroup("ide");
});
tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> {
t.setDescription("Generates Eclipse run configurations for this project.");
t.dependsOn("downloadAssets");
t.setGroup("ide");
});
tasks.register("cleanEclipseRuns", CleanEclipseRunsTask.class, t -> {
t.setDescription("Removes Eclipse run configurations for this project.");
t.setGroup("ide");
});
tasks.register("vscode", GenVsCodeProjectTask.class, t -> {
t.setDescription("Generates VSCode launch configurations.");
t.dependsOn("downloadAssets");
t.setGroup("ide");
});
}
private static void registerRunTasks(TaskContainer tasks) {
tasks.register("runClient", RunClientTask.class, t -> {
t.setDescription("Starts a development version of the Minecraft client.");
t.dependsOn("downloadAssets");
t.setGroup("fabric");
});
tasks.register("runServer", RunServerTask.class, t -> {
t.setDescription("Starts a development version of the Minecraft server.");
t.setGroup("fabric");
});
}
private static void registerDecompileTasks(TaskContainer tasks, Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
project.afterEvaluate((p) -> {
for (LoomDecompiler decompiler : extension.getDecompilers()) {
String taskName = (decompiler instanceof FabricFernFlowerDecompiler) ? "genSources" : "genSourcesWith" + decompiler.name();
// decompiler will be passed to the constructor of GenerateSourcesTask
tasks.register(taskName, GenerateSourcesTask.class, decompiler);
}
});
}
}

View File

@@ -49,10 +49,10 @@ import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.mappings.MojangMappingsDependency;
import net.fabricmc.lorenztiny.TinyMappingsJoiner;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;

View File

@@ -34,16 +34,17 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.fabricmc.loom.util.*;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
@@ -53,21 +54,29 @@ import org.gradle.jvm.tasks.Jar;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.build.JarRemapper;
import net.fabricmc.loom.build.MixinRefmapHelper;
import net.fabricmc.loom.build.NestedJars;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.LoggerFilter;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.ZipReprocessorUtil;
import net.fabricmc.loom.util.gradle.GradleSupport;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
public class RemapJarTask extends Jar {
private final RegularFileProperty input;
private final Property<Boolean> addNestedDependencies;
private final Property<Boolean> remapAccessWidener;
private final List<Action<TinyRemapper.Builder>> remapOptions = new ArrayList<>();
private final Property<String> fromM;
private final Property<String> toM;
public JarRemapper jarRemapper;
private FileCollection classpath;
public RemapJarTask() {
super();
@@ -106,11 +115,8 @@ public class RemapJarTask extends Jar {
String fromM = this.fromM.get();
String toM = this.toM.get();
Set<File> classpathFiles = new LinkedHashSet<>(
project.getConfigurations().getByName("compileClasspath").getFiles()
);
Path[] classpath = classpathFiles.stream().map(File::toPath).filter((p) -> !input.equals(p) && Files.exists(p)).toArray(Path[]::new);
Path[] classpath = getRemapClasspath();
LoggerFilter.replaceSystemOut();
TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
@@ -122,6 +128,11 @@ public class RemapJarTask extends Jar {
}
}
// Apply any requested options to tiny remapper
for (Action<TinyRemapper.Builder> remapOption : this.remapOptions) {
remapOption.execute(remapperBuilder);
}
project.getLogger().lifecycle(":remapping " + input.getFileName());
StringBuilder rc = new StringBuilder("Remap classpath: ");
@@ -157,23 +168,25 @@ public class RemapJarTask extends Jar {
if (MixinRefmapHelper.addRefmapName(extension.getRefmapName(), extension.getMixinJsonVersion(), output)) {
project.getLogger().debug("Transformed mixin reference maps in output JAR!");
}
if (extension.isForge()) {
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + output.toUri()), ImmutableMap.of("create", false))) {
Path refmapPath = fs.getPath(extension.getRefmapName());
if (Files.exists(refmapPath)) {
try (Reader refmapReader = Files.newBufferedReader(refmapPath, StandardCharsets.UTF_8)) {
JsonObject refmapElement = new JsonParser().parse(refmapReader).getAsJsonObject().deepCopy();
Files.delete(refmapPath);
if (refmapElement.has("data")) {
JsonObject data = refmapElement.get("data").getAsJsonObject();
if (data.has("named:intermediary")) {
data.add("searge", data.get("named:intermediary").deepCopy());
data.remove("named:intermediary");
}
}
Files.write(refmapPath, new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(refmapElement).getBytes(StandardCharsets.UTF_8));
}
}
@@ -186,16 +199,9 @@ public class RemapJarTask extends Jar {
}
}
/*try {
if (modJar.exists()) {
Files.move(modJar, modJarUnmappedCopy);
extension.addUnmappedMod(modJarUnmappedCopy);
}
Files.move(modJarOutput, modJar);
} catch (IOException e) {
throw new RuntimeException(e);
}*/
if (isReproducibleFileOrder() || isPreserveFileTimestamps()) {
ZipReprocessorUtil.reprocessZip(output.toFile(), isReproducibleFileOrder(), isPreserveFileTimestamps());
}
}
public void scheduleRemap() throws Throwable {
@@ -214,16 +220,7 @@ public class RemapJarTask extends Jar {
String toM = this.toM.get();
if (extension.isRootProject()) {
Set<File> classpathFiles = new LinkedHashSet<>(
project.getConfigurations().getByName("compileClasspath").getFiles()
);
Path[] classpath = classpathFiles.stream()
.map(File::toPath)
.filter(Files::exists)
.toArray(Path[]::new);
jarRemapper.addToClasspath(classpath);
jarRemapper.addToClasspath(getRemapClasspath());
jarRemapper.addMappings(TinyRemapperMappingsHelper.create(extension.isForge() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(), fromM, toM, false));
}
@@ -234,6 +231,9 @@ public class RemapJarTask extends Jar {
}
}
// Add remap options to the jar remapper
jarRemapper.addOptions(this.remapOptions);
jarRemapper.scheduleRemap(input, output)
.supplyAccessWidener((remapData, remapper) -> {
if (getRemapAccessWidener().getOrElse(false) && extension.accessWidener != null) {
@@ -276,6 +276,19 @@ public class RemapJarTask extends Jar {
});
}
private Path[] getRemapClasspath() {
FileCollection files = this.classpath;
if (files == null) {
files = getProject().getConfigurations().getByName("compileClasspath");
}
return files.getFiles().stream()
.map(File::toPath)
.filter(Files::exists)
.toArray(Path[]::new);
}
@InputFile
public RegularFileProperty getInput() {
return input;
@@ -291,6 +304,20 @@ public class RemapJarTask extends Jar {
return remapAccessWidener;
}
public void remapOptions(Action<TinyRemapper.Builder> action) {
this.remapOptions.add(action);
}
public RemapJarTask classpath(FileCollection collection) {
if (this.classpath == null) {
this.classpath = collection;
} else {
this.classpath = this.classpath.plus(collection);
}
return this;
}
@Input
public Property<String> getFromM() {
return fromM;

View File

@@ -26,6 +26,8 @@ package net.fabricmc.loom.task;
import java.io.File;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Internal;
@@ -33,19 +35,29 @@ import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.ZipReprocessorUtil;
public class RemapSourcesJarTask extends AbstractLoomTask {
private Object input;
private Object output;
private String direction = "intermediary";
private SourceRemapper sourceRemapper = null;
private final Property<Boolean> archivePreserveFileTimestamps;
private final Property<Boolean> archiveReproducibleFileOrder;
public RemapSourcesJarTask() {
ObjectFactory objectFactory = getProject().getObjects();
archivePreserveFileTimestamps = objectFactory.property(Boolean.class);
archiveReproducibleFileOrder = objectFactory.property(Boolean.class);
}
@TaskAction
public void remap() throws Exception {
if (sourceRemapper == null) {
SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named"));
ZipReprocessorUtil.reprocessZip(getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false));
} else {
sourceRemapper.scheduleRemapSources(getInput(), getOutput());
sourceRemapper.scheduleRemapSources(getInput(), getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false));
}
}

View File

@@ -24,7 +24,7 @@
package net.fabricmc.loom.task;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
public class RunClientTask extends AbstractRunTask {
public RunClientTask() {

View File

@@ -24,7 +24,7 @@
package net.fabricmc.loom.task;
import net.fabricmc.loom.util.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfig;
public class RunServerTask extends AbstractRunTask {
public RunServerTask() {

View File

@@ -38,21 +38,14 @@ public class Checksum {
private static final Logger log = Logging.getLogger(Checksum.class);
public static boolean equals(File file, String checksum) {
if (file == null) {
if (file == null || !file.exists()) {
return false;
}
try {
//noinspection deprecation
HashCode hash = Files.asByteSource(file).hash(Hashing.sha1());
StringBuilder builder = new StringBuilder();
for (Byte hashBytes : hash.asBytes()) {
builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1));
}
log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?");
return builder.toString().equals(checksum);
log.debug("Checksum check: '" + hash.toString() + "' == '" + checksum + "'?");
return hash.toString().equals(checksum);
} catch (IOException e) {
e.printStackTrace();
}

View File

@@ -29,10 +29,12 @@ import java.util.List;
import com.google.common.collect.ImmutableList;
import org.objectweb.asm.Opcodes;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
public class Constants {
public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/";
public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/";
public static final String VERSION_MANIFESTS = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
public static final String VERSION_MANIFESTS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
@@ -58,9 +60,11 @@ public class Constants {
public static final String INCLUDE = "include";
public static final String MINECRAFT = "minecraft";
public static final String MINECRAFT_DEPENDENCIES = "minecraftLibraries";
public static final String MINECRAFT_REMAP_CLASSPATH = "minecraftRemapClasspath";
public static final String MINECRAFT_NAMED = "minecraftNamed";
public static final String MAPPINGS = "mappings";
public static final String MAPPINGS_FINAL = "mappingsFinal";
public static final String LOADER_DEPENDENCIES = "loaderLibraries";
public static final String SRG = "srg";
public static final String MCP_CONFIG = "mcp";
public static final String FORGE = "forge";

View File

@@ -35,9 +35,9 @@ import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
public class DownloadUtil {
public static boolean refreshDeps = false;
import net.fabricmc.loom.LoomGradlePlugin;
public class DownloadUtil {
/**
* Download from the given {@link URL} to the given {@link File} so long as there are differences between them.
*
@@ -62,7 +62,7 @@ public class DownloadUtil {
public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException {
HttpURLConnection connection = (HttpURLConnection) from.openConnection();
if (refreshDeps) {
if (LoomGradlePlugin.refreshDeps) {
getETagFile(to).delete();
to.delete();
}
@@ -192,7 +192,7 @@ public class DownloadUtil {
* @param bytes The number of bytes
* @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate
*/
private static String toNiceSize(long bytes) {
public static String toNiceSize(long bytes) {
if (bytes < 1024) {
return bytes + " B";
} else if (bytes < 1024 * 1024) {

View File

@@ -24,43 +24,43 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
public final class FileSystemUtil {
public static class FileSystemDelegate implements AutoCloseable {
private final FileSystem fileSystem;
private final boolean owner;
public static class FileSystemDelegate implements AutoCloseable {
private final FileSystem fileSystem;
private final boolean owner;
public FileSystemDelegate(FileSystem fileSystem, boolean owner) {
this.fileSystem = fileSystem;
this.owner = owner;
}
public FileSystemDelegate(FileSystem fileSystem, boolean owner) {
this.fileSystem = fileSystem;
this.owner = owner;
}
public FileSystem get() {
return fileSystem;
}
public FileSystem get() {
return fileSystem;
}
@Override
public void close() throws IOException {
if (owner) {
fileSystem.close();
}
}
}
@Override
public void close() throws IOException {
if (owner) {
fileSystem.close();
}
}
}
private FileSystemUtil() {
private FileSystemUtil() {
}
}
private static final Map<String, String> jfsArgsCreate = new HashMap<>();
private static final Map<String, String> jfsArgsEmpty = new HashMap<>();
private static final Map<String, String> jfsArgsCreate = new HashMap<>();
private static final Map<String, String> jfsArgsEmpty = new HashMap<>();
static {
jfsArgsCreate.put("create", "true");
}
static {
jfsArgsCreate.put("create", "true");
}
public static FileSystemDelegate getJarFileSystem(File file, boolean create) throws IOException {
return getJarFileSystem(file.toURI(), create);
return getJarFileSystem(file.toURI(), create);
}
public static FileSystemDelegate getJarFileSystem(Path path, boolean create) throws IOException {
@@ -68,17 +68,18 @@ public final class FileSystemUtil {
}
public static FileSystemDelegate getJarFileSystem(URI uri, boolean create) throws IOException {
URI jarUri;
try {
jarUri = new URI("jar:" + uri.getScheme(), uri.getHost(), uri.getPath(), uri.getFragment());
} catch (URISyntaxException e) {
throw new IOException(e);
}
URI jarUri;
try {
return new FileSystemDelegate(FileSystems.newFileSystem(jarUri, create ? jfsArgsCreate : jfsArgsEmpty), true);
} catch (FileSystemAlreadyExistsException e) {
return new FileSystemDelegate(FileSystems.getFileSystem(jarUri), false);
}
}
}
try {
jarUri = new URI("jar:" + uri.getScheme(), uri.getHost(), uri.getPath(), uri.getFragment());
} catch (URISyntaxException e) {
throw new IOException(e);
}
try {
return new FileSystemDelegate(FileSystems.newFileSystem(jarUri, create ? jfsArgsCreate : jfsArgsEmpty), true);
} catch (FileSystemAlreadyExistsException e) {
return new FileSystemDelegate(FileSystems.getFileSystem(jarUri), false);
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016, 2017, 2018 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.util;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
import org.gradle.api.logging.Logger;
import net.fabricmc.loom.LoomGradlePlugin;
public class HashedDownloadUtil {
public static void downloadIfInvalid(URL from, File to, String expectedHash, Logger logger, boolean quiet) throws IOException {
if (LoomGradlePlugin.refreshDeps) {
delete(to);
}
if (to.exists()) {
String sha1 = getSha1(to, logger);
if (expectedHash.equals(sha1)) {
// The hash in the sha1 file matches
return;
}
}
HttpURLConnection connection = (HttpURLConnection) from.openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
connection.connect();
int code = connection.getResponseCode();
if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
//Didn't get what we expected
throw new IOException(connection.getResponseMessage() + " for " + from);
}
long contentLength = connection.getContentLengthLong();
if (!quiet && contentLength >= 0) {
logger.info("'{}' Changed, downloading {}", to, DownloadUtil.toNiceSize(contentLength));
}
try { // Try download to the output
FileUtils.copyInputStreamToFile(connection.getInputStream(), to);
} catch (IOException e) {
delete(to); // Probably isn't good if it fails to copy/save
throw e;
}
if (!Checksum.equals(to, expectedHash)) {
String actualHash = Files.asByteSource(to).hash(Hashing.sha1()).toString();
delete(to);
throw new IOException(String.format("Downloaded file from %s to %s and got unexpected hash of %s expected %s", from, to, actualHash, expectedHash));
}
saveSha1(to, expectedHash, logger);
}
private static File getSha1File(File file) {
return new File(file.getAbsoluteFile().getParentFile(), file.getName() + ".sha1");
}
@Nullable
private static String getSha1(File to, Logger logger) {
File sha1File = getSha1File(to);
if (!sha1File.exists()) {
return null;
}
try {
return Files.asCharSource(sha1File, StandardCharsets.UTF_8).read();
} catch (IOException e) {
logger.warn("Error reading sha1 file '{}'.", sha1File);
return null;
}
}
private static void saveSha1(File to, String sha1, Logger logger) {
File sha1File = getSha1File(to);
try {
if (!sha1File.exists()) {
sha1File.createNewFile();
}
Files.asCharSink(sha1File, StandardCharsets.UTF_8).write(sha1);
} catch (IOException e) {
logger.warn("Error saving sha1 file '{}'.", sha1File, e);
}
}
public static void delete(File file) {
if (file.exists()) {
file.delete();
}
File sha1File = getSha1File(file);
if (sha1File.exists()) {
sha1File.delete();
}
}
}

View File

@@ -24,10 +24,10 @@
package net.fabricmc.loom.util;
import org.jetbrains.annotations.NotNull;
import java.io.PrintStream;
import org.jetbrains.annotations.NotNull;
public class LoggerFilter {
public static void replaceSystemOut() {
try {
@@ -38,10 +38,12 @@ public class LoggerFilter {
if (format.equals("unknown invokedynamic bsm: %s/%s%s (tag=%d iif=%b)%n")) {
return this;
}
return super.printf(format, args);
}
});
} catch (SecurityException ignored) {
// Failed to replace logger filter, just ignore
}
}
}

View File

@@ -41,9 +41,10 @@ import org.gradle.api.artifacts.Dependency;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.LaunchProvider;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.providers.LaunchProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.gradle.ProgressLogger;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.util.StitchUtil;
@@ -62,16 +63,27 @@ public class SourceRemapper {
public static void remapSources(Project project, File input, File output, boolean named) throws Exception {
SourceRemapper sourceRemapper = new SourceRemapper(project, named);
sourceRemapper.scheduleRemapSources(input, output);
sourceRemapper.scheduleRemapSources(input, output, false, true);
sourceRemapper.remapAll();
}
@Deprecated
public void scheduleRemapSources(File source, File destination) throws Exception {
scheduleRemapSources(source, destination, false, true); // Not reproducable by default, old behavior
}
public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
remapTasks.add((logger) -> {
try {
logger.progress("remapping sources - " + source.getName());
remapSourcesInner(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);
}
});
@@ -178,6 +190,7 @@ public class SourceRemapper {
m.getClassPath().add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
m.getClassPath().add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
if (extension.isForge()) {
m.getClassPath().add(extension.getMinecraftMappedProvider().getSrgJar().toPath());
}
@@ -217,7 +230,7 @@ public class SourceRemapper {
Mercury m = new Mercury();
m.setGracefulClasspathChecks(true);
for (File file : project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()) {
for (File file : project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()) {
m.getClassPath().add(file.toPath());
}

View File

@@ -1,12 +1,15 @@
package net.fabricmc.loom.util;
import org.gradle.internal.impldep.com.google.api.client.repackaged.com.google.common.base.Function;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ThreadingUtils {
@@ -24,6 +27,7 @@ public class ThreadingUtils {
try {
ExecutorService service = Executors.newFixedThreadPool(Math.min(jobs.size(), Runtime.getRuntime().availableProcessors() / 2));
List<Future<?>> futures = new LinkedList<>();
for (UnsafeRunnable runnable : jobs) {
futures.add(service.submit(() -> {
try {
@@ -33,9 +37,11 @@ public class ThreadingUtils {
}
}));
}
for (Future<?> future : futures) {
future.get();
}
service.shutdownNow();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
@@ -57,6 +63,8 @@ public class ThreadingUtils {
try {
ExecutorService service = Executors.newFixedThreadPool(Math.min(jobs.size(), Runtime.getRuntime().availableProcessors() / 2));
List<Future<T>> futures = new LinkedList<>();
List<T> result = new ArrayList<>();
for (UnsafeCallable<T> runnable : jobs) {
futures.add(service.submit(() -> {
try {
@@ -66,10 +74,11 @@ public class ThreadingUtils {
}
}));
}
List<T> result = new ArrayList<>();
for (Future<T> future : futures) {
result.add(future.get());
}
service.shutdownNow();
return result;
} catch (InterruptedException | ExecutionException e) {

View File

@@ -0,0 +1,79 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016, 2017, 2018 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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class ZipReprocessorUtil {
private ZipReprocessorUtil() { }
public static void reprocessZip(File file, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws IOException {
if (!reproducibleFileOrder && preserveFileTimestamps) {
return;
}
try (ZipFile zipFile = new ZipFile(file)) {
ZipEntry[] entries;
if (reproducibleFileOrder) {
entries = zipFile.stream().sorted((a, b) -> a.getName().compareTo(b.getName())).toArray(ZipEntry[]::new);
} else {
entries = zipFile.stream().toArray(ZipEntry[]::new);
}
ByteArrayOutputStream outZip = new ByteArrayOutputStream(zipFile.size());
try (ZipOutputStream zipOutputStream = new ZipOutputStream(outZip)) {
for (ZipEntry entry : entries) {
if (!preserveFileTimestamps) {
entry.setTime(0);
}
zipOutputStream.putNextEntry(entry);
InputStream inputStream = zipFile.getInputStream(entry);
byte[] buf = new byte[1024];
int length;
while ((length = inputStream.read(buf)) > 0) {
zipOutputStream.write(buf, 0, length);
}
zipOutputStream.closeEntry();
}
}
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
outZip.writeTo(fileOutputStream);
}
}
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util;
package net.fabricmc.loom.util.gradle;
import java.lang.reflect.Method;

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
package net.fabricmc.loom.util.progress;
package net.fabricmc.loom.util.gradle;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

View File

@@ -24,14 +24,6 @@
package net.fabricmc.loom.util.srg;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
import org.apache.logging.log4j.util.Strings;
import org.gradle.api.logging.Logger;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Path;
@@ -40,6 +32,15 @@ import java.util.List;
import java.util.function.UnaryOperator;
import java.util.zip.ZipEntry;
import org.apache.logging.log4j.util.Strings;
import org.gradle.api.logging.Logger;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
/**
* Remaps AT classes from SRG to Yarn.
*
@@ -47,7 +48,7 @@ import java.util.zip.ZipEntry;
*/
public final class AtRemapper {
public static void remap(Logger logger, Path jar, TinyTree mappings) throws IOException {
ZipUtil.transformEntries(jar.toFile(), new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("META-INF/accesstransformer.cfg", new StringZipEntryTransformer() {
ZipUtil.transformEntries(jar.toFile(), new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("META-INF/accesstransformer.cfg", new StringZipEntryTransformer() {
@Override
protected String transform(ZipEntry zipEntry, String input) {
String[] lines = input.split("\n");
@@ -62,16 +63,19 @@ public final class AtRemapper {
}
String[] parts = line.split("\\s+");
if (parts.length < 2) {
logger.warn("Invalid AT Line: " + line);
output.add(i, line);
continue;
}
String name = parts[1].replace('.', '/');
parts[1] = CollectionUtil.find(
mappings.getClasses(),
def -> def.getName("srg").equals(name)
).map(def -> def.getName("named")).orElse(name).replace('/', '.');
if (parts.length >= 3) {
if (parts[2].contains("(")) {
parts[2] = parts[2].substring(0, parts[2].indexOf('(')) + remapDescriptor(parts[2].substring(parts[2].indexOf('(')), s -> {
@@ -97,25 +101,31 @@ public final class AtRemapper {
StringBuilder result = new StringBuilder();
boolean insideClassName = false;
StringBuilder className = new StringBuilder();
while (true) {
int c = reader.read();
if (c == -1) {
break;
}
if ((char) c == ';') {
insideClassName = false;
result.append(classMappings.apply(className.toString()));
}
if (insideClassName) {
className.append((char) c);
} else {
result.append((char) c);
}
if (!insideClassName && (char) c == 'L') {
insideClassName = true;
className.setLength(0);
}
}
return result.toString();
} catch (IOException e) {
throw new AssertionError(e);

View File

@@ -24,27 +24,32 @@
package net.fabricmc.loom.util.srg;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
import org.apache.logging.log4j.util.Strings;
import org.gradle.api.logging.Logger;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.logging.log4j.util.Strings;
import org.gradle.api.logging.Logger;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
/**
* Remaps coremod class names from SRG to Yarn.
*
@@ -101,7 +106,7 @@ public final class CoreModClassRemapper {
}
}
}
if (!lines.equals(output)) {
try (Writer writer = Files.newBufferedWriter(js, StandardCharsets.UTF_8, StandardOpenOption.WRITE)) {
writer.write(String.join(Strings.LINE_SEPARATOR, output));

View File

@@ -1,10 +1,5 @@
package net.fabricmc.loom.util.srg;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.IMappingProvider;
import org.zeroturnaround.zip.ZipUtil;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -13,6 +8,12 @@ import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.IMappingProvider;
public class InnerClassRemapper {
public static IMappingProvider of(Path fromJar, TinyTree mappingsWithSrg, String from, String to) throws IOException {
return sink -> {
@@ -33,11 +34,13 @@ public class InnerClassRemapper {
ZipUtil.iterate(inputStream, (in, zipEntry) -> {
if (!zipEntry.isDirectory() && zipEntry.getName().contains("$") && zipEntry.getName().endsWith(".class")) {
String className = zipEntry.getName().substring(0, zipEntry.getName().length() - 6);
if (!availableClasses.containsKey(className)) {
String parentName = className.substring(0, className.indexOf('$'));
String childName = className.substring(className.indexOf('$') + 1);
String remappedParentName = availableClasses.getOrDefault(parentName, parentName);
String remappedName = remappedParentName + "$" + childName;
if (!className.equals(remappedName)) {
action.accept(className, remappedName);
}

View File

@@ -1,13 +1,5 @@
package net.fabricmc.loom.util.srg;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import org.gradle.util.GradleVersion;
import org.zeroturnaround.zip.ZipUtil;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -20,6 +12,15 @@ import java.util.jar.JarOutputStream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import org.gradle.util.GradleVersion;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
public class SpecialSourceExecutor {
public static Path produceSrgJar(Project project, MappingsProvider provider, String side, File specialSourceJar, Path officialJar, Path srgPath)
throws Exception {
@@ -30,6 +31,7 @@ public class SpecialSourceExecutor {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
Path stripped = extension.getProjectBuildCache().toPath().resolve(officialJar.getFileName().toString().substring(0, officialJar.getFileName().toString().length() - 4) + "-filtered.jar");
Files.deleteIfExists(stripped);
try (JarOutputStream output = new JarOutputStream(Files.newOutputStream(stripped))) {
ZipUtil.iterate(officialJar.toFile(), (in, zipEntry) -> {
if (filter.contains(zipEntry.getName())) {
@@ -39,10 +41,11 @@ public class SpecialSourceExecutor {
}
});
}
Path output = extension.getProjectBuildCache().toPath().resolve(officialJar.getFileName().toString().substring(0, officialJar.getFileName().toString().length() - 4) + "-srg-output.jar");
Files.deleteIfExists(output);
String[] args = new String[]{
String[] args = new String[] {
"--in-jar",
stripped.toAbsolutePath().toString(),
"--out-jar",
@@ -59,6 +62,7 @@ public class SpecialSourceExecutor {
java.setMain("net.md_5.specialsource.SpecialSource");
java.setStandardOutput(System.out);
java.exec();
if (GradleVersion.current().compareTo(GradleVersion.version("6.0.0")) >= 0) {
java.setEnabled(false);
} else {

View File

@@ -1,17 +1,19 @@
package net.fabricmc.loom.util.srg;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree;
import org.cadixdev.lorenz.io.srg.SrgWriter;
import org.gradle.api.logging.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.cadixdev.lorenz.io.srg.SrgWriter;
import org.gradle.api.logging.Logger;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree;
public class SrgNamedWriter {
public static void writeTo(Logger logger, Path srgFile, TinyTree mappings, String from, String to) throws IOException {
Files.deleteIfExists(srgFile);
try (SrgWriter writer = new SrgWriter(Files.newBufferedWriter(srgFile))) {
try (TinyMappingsReader reader = new TinyMappingsReader(mappings, from, to)) {
writer.write(reader.read());

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>%GROUP%</groupId>
<artifactId>%NAME%</artifactId>
<version>%VERSION%</version>
</project>