diff --git a/build.gradle b/build.gradle index ab93368e..60cc4ac2 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ targetCompatibility = 1.8 group = 'net.fabricmc' archivesBaseName = project.name -version = '0.0.13-SNAPSHOT' +version = '0.0.14-SNAPSHOT' def build = "local" def ENV = System.getenv() @@ -33,11 +33,12 @@ dependencies { implementation ('commons-io:commons-io:2.6') implementation ('org.zeroturnaround:zt-zip:1.13') implementation ('com.google.code.gson:gson:2.8.5') - implementation ('com.google.guava:guava:27.0-jre') - implementation ('net.fabricmc:stitch:0.1.0.11') - implementation ('net.fabricmc:tiny-remapper:0.1.0.18') { + implementation ('com.google.guava:guava:27.0.1-jre') + implementation ('net.fabricmc:stitch:0.1.0.16') + implementation ('net.fabricmc:tiny-remapper:0.1.0.19') { transitive = false } + implementation ('org.benf:cfr:0.136') implementation ('net.fabricmc:sponge-mixin:0.7.11.3') { exclude module: 'launchwrapper' diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index e7e1163c..a27916a4 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -24,10 +24,7 @@ package net.fabricmc.loom; -import net.fabricmc.loom.task.GenIdeaProjectTask; -import net.fabricmc.loom.task.RemapJar; -import net.fabricmc.loom.task.RunClientTask; -import net.fabricmc.loom.task.RunServerTask; +import net.fabricmc.loom.task.*; import org.gradle.api.Project; public class LoomGradlePlugin extends AbstractPlugin { @@ -37,6 +34,8 @@ public class LoomGradlePlugin extends AbstractPlugin { makeTask("remapJar", RemapJar.class); + makeTask("genSources", GenSourcesTask.class); + makeTask("genIdeaWorkspace", GenIdeaProjectTask.class).dependsOn("idea").setGroup("ide"); makeTask("runClient", RunClientTask.class).dependsOn("buildNeeded").setGroup("minecraftMapped"); diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftJarProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftJarProvider.java index 37aaf139..a8c64063 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftJarProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftJarProvider.java @@ -71,7 +71,7 @@ public class MinecraftJarProvider { private void initFiles(Project project, MinecraftProvider minecraftProvider) { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); PomfProvider pomfProvider = extension.getPomfProvider(); - MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), minecraftProvider.minecraftVersion + "-merged.jar"); + MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-merged.jar"); } public File getInputJar() { diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftLibraryProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftLibraryProvider.java index 08f0465a..e7c6f120 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftLibraryProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftLibraryProvider.java @@ -123,7 +123,7 @@ public class MinecraftLibraryProvider { private void initFiles(Project project, MinecraftProvider minecraftProvider) { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - MINECRAFT_LIBS = new File(extension.getUserCache(), minecraftProvider.minecraftVersion + "-libs"); + MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); } } diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java index 1a1b96b0..87dd4e06 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java @@ -25,10 +25,13 @@ package net.fabricmc.loom.providers; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.task.GenSourcesTask; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DependencyProvider; import net.fabricmc.loom.util.MapJarsTiny; +import org.gradle.api.Action; import org.gradle.api.Project; +import org.gradle.api.artifacts.repositories.IvyArtifactRepository; import java.io.File; import java.util.Collection; @@ -54,14 +57,16 @@ public class MinecraftMappedProvider extends DependencyProvider { if (!MINECRAFT_MAPPED_JAR.exists()) { throw new RuntimeException("mapped jar not found"); } - minecraftProvider.addDependency(MINECRAFT_MAPPED_JAR, project); + + String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getPomfProvider().pomfVersion; + project.getDependencies().add("compile", project.getDependencies().module("net.minecraft:minecraft:" + version)); } public void initFiles(Project project, MinecraftProvider minecraftProvider, PomfProvider pomfProvider) { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); this.minecraftProvider = minecraftProvider; - MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), minecraftProvider.minecraftVersion + "-intermediary.jar"); - MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), minecraftProvider.minecraftVersion + "-mapped-" + pomfProvider.pomfVersion + ".jar"); + MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary.jar"); + MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + pomfProvider.pomfVersion + ".jar"); } public Collection getMapperPaths() { diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java index d217fa04..c5c6d75c 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java @@ -75,10 +75,10 @@ public class MinecraftProvider extends DependencyProvider { private void initFiles(Project project) { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - MINECRAFT_JSON = new File(extension.getUserCache(), minecraftVersion + "-info.json"); - MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), minecraftVersion + "-client.jar"); - MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), minecraftVersion + "-server.jar"); - MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), minecraftVersion + "-merged.jar"); + MINECRAFT_JSON = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-info.json"); + MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); + MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); + MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); } diff --git a/src/main/java/net/fabricmc/loom/task/GenSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenSourcesTask.java new file mode 100644 index 00000000..dbcd6af5 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/task/GenSourcesTask.java @@ -0,0 +1,154 @@ +/* + * 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 com.google.common.base.Charsets; +import com.google.common.collect.ImmutableMap; +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.providers.MinecraftProvider; +import net.fabricmc.loom.providers.PomfProvider; +import net.fabricmc.loom.util.MinecraftVersionInfo; +import org.benf.cfr.reader.api.CfrDriver; +import org.benf.cfr.reader.api.ClassFileSource; +import org.benf.cfr.reader.api.OutputSinkFactory; +import org.benf.cfr.reader.api.SinkReturns; +import org.benf.cfr.reader.entities.Method; +import org.benf.cfr.reader.util.output.StreamDumper; +import org.gradle.api.DefaultTask; +import org.gradle.api.Project; +import org.gradle.api.tasks.TaskAction; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.*; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +public class GenSourcesTask extends DefaultTask { + public static File getSourcesJar(Project project) { + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + PomfProvider pomfProvider = extension.getPomfProvider(); + File mappedJar = pomfProvider.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) + "-sources.jar"); + } + + @TaskAction + public void genSources() throws IOException { + Project project = this.getProject(); + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + PomfProvider pomfProvider = extension.getPomfProvider(); + File mappedJar = pomfProvider.mappedProvider.getMappedJar(); + File sourcesJar = getSourcesJar(project); + + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + Set addedDirectories = new HashSet<>(); + + try (FileOutputStream fos = new FileOutputStream(sourcesJar); + JarOutputStream jos = new JarOutputStream(fos, manifest)) { + + project.getLogger().lifecycle(":generating sources JAR"); + CfrDriver driver = new CfrDriver.Builder() + .withOptions(ImmutableMap.of("renameillegalidents","true")) + .withOutputSink(new OutputSinkFactory() { + @Override + public List getSupportedSinks(SinkType sinkType, Collection collection) { + switch (sinkType) { + case PROGRESS: + return Collections.singletonList(SinkClass.STRING); + case JAVA: + return Collections.singletonList(SinkClass.DECOMPILED); + default: + return Collections.emptyList(); + } + } + + @Override + public Sink getSink(SinkType sinkType, SinkClass sinkClass) { + switch (sinkType) { + case PROGRESS: + return (t) -> getLogger().debug((String) t); + case JAVA: + //noinspection unchecked + return (Sink) new Sink() { + @Override + public void write(SinkReturns.Decompiled decompiled) { + String filename = decompiled.getPackageName().replace('.', '/'); + if (!filename.isEmpty()) filename += "/"; + filename += decompiled.getClassName() + ".java"; + + String[] path = filename.split("/"); + String pathPart = ""; + for (int i = 0; i < path.length - 1; i++) { + pathPart += path[i] + "/"; + if (addedDirectories.add(pathPart)) { + JarEntry entry = new JarEntry(pathPart); + entry.setTime(new Date().getTime()); + + try { + jos.putNextEntry(entry); + jos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + byte[] data = decompiled.getJava().getBytes(Charsets.UTF_8); + JarEntry entry = new JarEntry(filename); + entry.setTime(new Date().getTime()); + entry.setSize(data.length); + + try { + jos.putNextEntry(entry); + jos.write(data); + jos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + default: + return (t) -> {}; + } + } + }) + .build(); + + driver.analyse(Collections.singletonList(mappedJar.getAbsolutePath())); + } + } +}