Reformat to use Fabric API's checkstyle (#137)

* Reformat to use Fabric API's checkstyle

* Fix

* Fix

* Update

* Travis and fixes

* possible fix for checkstyle?

* Helps if i push the checkstyle.xml file...

* Log checkstyle issues to console - used by travis

* Fix some more issues

* opps
dev/0.11
modmuss50 2019-11-02 20:23:27 +00:00 committed by GitHub
parent 2bd339241f
commit f85daec559
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 2129 additions and 1655 deletions

4
.gitignore vendored
View File

@ -17,4 +17,6 @@
!/LICENSE !/LICENSE
!/README.md !/README.md
!/settings.gradle !/settings.gradle
!/Jenkinsfile !/Jenkinsfile
!/.travis.yml
!/checkstyle.xml

12
.travis.yml Normal file
View File

@ -0,0 +1,12 @@
language: java
install: true
jdk:
- openjdk8
script:
- chmod +x gradlew
- ./gradlew check build test --stacktrace
notifications:
email: false

View File

@ -5,6 +5,7 @@ plugins {
id 'idea' id 'idea'
id 'eclipse' id 'eclipse'
id 'groovy' id 'groovy'
id 'checkstyle'
} }
sourceCompatibility = 1.8 sourceCompatibility = 1.8
@ -60,6 +61,12 @@ dependencies {
testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") testImplementation("org.spockframework:spock-core:1.3-groovy-2.4")
} }
configurations.all {
resolutionStrategy {
force 'org.codehaus.groovy:groovy-all:2.4.12'
}
}
jar { jar {
manifest { manifest {
attributes 'Implementation-Version': version + " Build(" + build + ")" attributes 'Implementation-Version': version + " Build(" + build + ")"
@ -82,6 +89,15 @@ license {
exclude '**/loom/util/DownloadUtil.java' exclude '**/loom/util/DownloadUtil.java'
} }
checkstyle {
configFile = file("checkstyle.xml")
toolVersion = '8.25'
}
checkstyleMain {
logging.setLevel(LogLevel.LIFECYCLE)
}
gradlePlugin { gradlePlugin {
plugins { plugins {
fabricLoom { fabricLoom {

162
checkstyle.xml Normal file
View File

@ -0,0 +1,162 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java"/>
<module name="NewlineAtEndOfFile"/>
<!-- disallow trailing whitespace -->
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="message" value="trailing whitespace"/>
</module>
<!-- note: RegexpMultiline shows nicer messages than Regexp, but has to be outside TreeWalker -->
<!-- disallow multiple consecutive blank lines -->
<module name="RegexpMultiline">
<property name="format" value="\n[\r\t ]*\n[\r\t ]*\n"/>
<property name="message" value="adjacent blank lines"/>
</module>
<!-- disallow blank after { -->
<module name="RegexpMultiline">
<property name="format" value="\{[\r\t ]*\n[\r\t ]*\n"/>
<property name="message" value="blank line after '{'"/>
</module>
<!-- disallow blank before } -->
<module name="RegexpMultiline">
<property name="format" value="\n[\r\t ]*\n[\r\t ]*\}"/>
<property name="message" value="blank line before '}'"/>
</module>
<!-- require blank before { in the same indentation level -->
<module name="RegexpMultiline">
<!-- the regex works as follows:
It matches (=fails) for \n<indentation><something>\n<same indentation><control statement>[...]{\n
while <something> is a single line comment, it'll look for a blank line one line earlier
if <something> is a space, indicating a formatting error or ' */', it'll ignore the instance
if <something> is a tab, indicating a continued line, it'll ignore the instance
<control statement> is 'if', 'do', 'while', 'for', 'try' or nothing (instance initializer block)
- first \n: with positive lookbehind (?<=\n) to move the error marker to a more reasonable place
- capture tabs for <indentation>, later referenced via \1
- remaining preceding line as a non-comment (doesn't start with '/', '//', ' ' or '\t') or multiple lines where all but the first are a single line comment with the same indentation
- new line
- <indentation> as captured earlier
- <control statement> as specified above
- { before the next new line -->
<property name="format" value="(?&lt;=\n)([\t]+)(?:[^/\n \t][^\n]*|/[^/\n][^\n]*|[^/\n][^\n]*(\n\1//[^\n]*)+)\n\1(|(if|do|while|for|try)[^\n]+)\{[\r\t ]*\n"/>
<property name="message" value="missing blank line before block at same indentation level"/>
</module>
<!-- require blank after } in the same indentation level -->
<module name="RegexpMultiline">
<!-- \n<indentation>}\n<same indentation><whatever unless newline, '}' or starting with cas(e) or def(ault)> -->
<property name="format" value="(?&lt;=\n)([\t]+)\}\n\1(?:[^\r\n\}cd]|c[^\r\na]|ca[^\r\ns]|d[^\r\ne]|de[^\r\nf])"/>
<property name="message" value="missing blank line after block at same indentation level"/>
</module>
<module name="TreeWalker">
<!-- Ensure all imports are ship shape -->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<module name="ImportOrder">
<property name="groups" value="java,javax,*,net.minecraft,net.fabricmc"/>
<property name="ordered" value="false"/><!-- the plugin orders alphabetically without considering separators.. -->
<property name="separated" value="true"/>
<property name="option" value="top"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
</module>
<!-- Ensures braces are at the end of a line -->
<module name="LeftCurly"/>
<module name="RightCurly"/>
<!-- single line statements on one line, -->
<module name="NeedBraces">
<property name="tokens" value="LITERAL_IF,LITERAL_FOR,LITERAL_WHILE"/>
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="NeedBraces">
<property name="tokens" value="LITERAL_ELSE,LITERAL_DO"/>
<property name="allowSingleLineStatement" value="false"/>
</module>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="allowMultipleEmptyLines" value="false"/>
<!-- exclude METHOD_DEF and VARIABLE_DEF -->
<property name="tokens" value="PACKAGE_DEF,IMPORT,STATIC_IMPORT,CLASS_DEF,INTERFACE_DEF,ENUM_DEF,STATIC_INIT,INSTANCE_INIT,CTOR_DEF"/>
</module>
<module name="OperatorWrap"/>
<module name="SeparatorWrap">
<property name="tokens" value="DOT,ELLIPSIS,AT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="COMMA,SEMI"/>
<property name="option" value="eol"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="8"/>
<property name="caseIndent" value="0"/>
<property name="throwsIndent" value="8"/>
<property name="arrayInitIndent" value="8"/>
<property name="lineWrappingIndentation" value="16"/>
</module>
<module name="ParenPad"/>
<module name="NoWhitespaceBefore"/>
<module name="NoWhitespaceAfter">
<!-- allow ARRAY_INIT -->
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP"/>
</module>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround">
<!-- Allow PLUS, MINUS, MUL, DIV as they may be more readable without spaces in some cases -->
<property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV_ASSIGN,DO_WHILE,EQUAL,GE,GT,LAMBDA,LAND,LCURLY,LE,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="GenericWhitespace"/>
<module name="CommentsIndentation"/>
<module name="ArrayTypeStyle"/>
<module name="DefaultComesLast">
<property name="skipIfLastAndSharedWithCase" value="true"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<module name="AnnotationLocation"/>
<module name="MissingOverride"/>
<!-- By default this allows catch blocks with only comments -->
<module name="EmptyCatchBlock"/>
<!-- Enforce tabs -->
<module name="RegexpSinglelineJava">
<property name="format" value="^\t* ([^*]|\*[^ /])"/>
<property name="message" value="non-tab indentation"/>
</module>
<module name="OuterTypeFilename"/>
<!--<module name="InvalidJavadocPosition"/>-->
<module name="JavadocParagraph"/>
<module name="JavadocStyle"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param,@return,@throws,@deprecated"/>
</module>
</module>
</module>

View File

@ -24,13 +24,16 @@
package net.fabricmc.loom; package net.fabricmc.loom;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import groovy.util.Node; import groovy.util.Node;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.util.*;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
@ -54,13 +57,16 @@ import org.gradle.api.tasks.scala.ScalaCompile;
import org.gradle.plugins.ide.eclipse.model.EclipseModel; import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.gradle.plugins.ide.idea.model.IdeaModel; import org.gradle.plugins.ide.idea.model.IdeaModel;
import java.io.File; import net.fabricmc.loom.providers.MappingsProvider;
import java.io.IOException; import net.fabricmc.loom.providers.MinecraftProvider;
import java.util.HashSet; import net.fabricmc.loom.task.RemapJarTask;
import java.util.Map; import net.fabricmc.loom.task.RemapSourcesJarTask;
import java.util.Optional; import net.fabricmc.loom.util.Constants;
import java.util.Set; import net.fabricmc.loom.util.GroovyXmlUtil;
import java.util.function.Predicate; import net.fabricmc.loom.util.LoomDependencyManager;
import net.fabricmc.loom.util.NestedJars;
import net.fabricmc.loom.util.RemappedConfigurationEntry;
import net.fabricmc.loom.util.SetupIntelijRunConfigs;
public class AbstractPlugin implements Plugin<Project> { public class AbstractPlugin implements Plugin<Project> {
protected Project project; protected Project project;
@ -116,6 +122,7 @@ public class AbstractPlugin implements Plugin<Project> {
compileModsMappedConfig.setTransitive(false); // Don't get transitive deps of already remapped mods 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());
if (entry.isOnModCompileClasspath()) { if (entry.isOnModCompileClasspath()) {
extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration()); extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration());
extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration()); extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration());
@ -137,15 +144,17 @@ public class AbstractPlugin implements Plugin<Project> {
configureScala(); configureScala();
Map<Project, Set<Task>> taskMap = project.getAllTasks(true); Map<Project, Set<Task>> taskMap = project.getAllTasks(true);
for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) {
Project project = entry.getKey(); Project project = entry.getKey();
Set<Task> taskSet = entry.getValue(); Set<Task> taskSet = entry.getValue();
for (Task task : taskSet) { for (Task task : taskSet) {
if (task instanceof JavaCompile if (task instanceof JavaCompile && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) {
&& !(task.getName().contains("Test")) && !(task.getName().contains("test"))) {
JavaCompile javaCompileTask = (JavaCompile) task; JavaCompile javaCompileTask = (JavaCompile) task;
javaCompileTask.doFirst(task1 -> { javaCompileTask.doFirst(task1 -> {
project.getLogger().lifecycle(":setting java compiler args"); project.getLogger().lifecycle(":setting java compiler args");
try { try {
javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
@ -166,30 +175,31 @@ public class AbstractPlugin implements Plugin<Project> {
return project; return project;
} }
protected void configureScala() { protected void configureScala() {
project.afterEvaluate(proj -> { project.afterEvaluate(proj -> {
if (project.getPluginManager().hasPlugin("scala")) { if (project.getPluginManager().hasPlugin("scala")) {
ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala");
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
project.getLogger().warn(":configuring scala compilation processing"); project.getLogger().warn(":configuring scala compilation processing");
try {
task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); try {
task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath());
} catch (IOException e) { task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary");
e.printStackTrace(); } catch (IOException e) {
} e.printStackTrace();
} }
}); }
} });
}
/** /**
* Permit to add a Maven repository to a target project * Permit to add a Maven repository to a target project.
* *
* @param target The garget project * @param target The garget project
* @param name The name of the repository * @param name The name of the repository
* @param url The URL of the repository * @param url The URL of the repository
* @return An object containing the name and the URL of the repository that can be modified later * @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 MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) {
@ -200,7 +210,7 @@ public class AbstractPlugin implements Plugin<Project> {
} }
/** /**
* Add Minecraft dependencies to IDE dependencies * Add Minecraft dependencies to IDE dependencies.
*/ */
protected void configureIDEs() { protected void configureIDEs() {
// IDEA // IDEA
@ -236,6 +246,7 @@ public class AbstractPlugin implements Plugin<Project> {
if (dep instanceof ResolvedDependencyResult) { if (dep instanceof ResolvedDependencyResult) {
if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) { if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) {
ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId()); ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId());
if (predicate.test(mci)) { if (predicate.test(mci)) {
addModule(project, configuration, dep); addModule(project, configuration, dep);
found = true; found = true;
@ -251,7 +262,7 @@ public class AbstractPlugin implements Plugin<Project> {
} }
/** /**
* Add Minecraft dependencies to compile time * Add Minecraft dependencies to compile time.
*/ */
protected void configureCompile() { protected void configureCompile() {
JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
@ -264,12 +275,18 @@ public class AbstractPlugin implements Plugin<Project> {
// Add Mixin dependencies // Add Mixin dependencies
Project p = project; Project p = project;
while (true) { while (true) {
boolean found = false; boolean found = false;
for (DependencyResult dep : p.getBuildscript().getConfigurations().getByName("classpath").getIncoming().getResolutionResult().getRoot().getDependencies()) { for (DependencyResult dep : p.getBuildscript().getConfigurations().getByName("classpath").getIncoming().getResolutionResult().getRoot().getDependencies()) {
found = findAndAddModule(project, "annotationProcessor", dep, (mci) -> ("net.fabricmc".equals(mci.getGroup()) && "fabric-mixin-compile-extensions".equals(mci.getModule()))); found = findAndAddModule(project, "annotationProcessor", dep, (mci) -> ("net.fabricmc".equals(mci.getGroup()) && "fabric-mixin-compile-extensions".equals(mci.getModule())));
} }
if (found || AbstractPlugin.isRootProject(p)) break;
if (found || AbstractPlugin.isRootProject(p)) {
break;
}
p = p.getRootProject(); p = p.getRootProject();
} }
@ -330,6 +347,7 @@ public class AbstractPlugin implements Plugin<Project> {
RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar"); RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar");
assert remapJarTask != null; assert remapJarTask != null;
if (!remapJarTask.getInput().isPresent()) { if (!remapJarTask.getInput().isPresent()) {
jarTask.setClassifier("dev"); jarTask.setClassifier("dev");
remapJarTask.setClassifier(""); remapJarTask.setClassifier("");
@ -344,8 +362,10 @@ public class AbstractPlugin implements Plugin<Project> {
project1.getTasks().getByName("build").dependsOn(remapJarTask); project1.getTasks().getByName("build").dependsOn(remapJarTask);
Map<Project, Set<Task>> taskMap = project.getAllTasks(true); Map<Project, Set<Task>> taskMap = project.getAllTasks(true);
for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) {
Set<Task> taskSet = entry.getValue(); Set<Task> taskSet = entry.getValue();
for (Task task : taskSet) { for (Task task : taskSet) {
if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) { 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 //Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects
@ -384,6 +404,7 @@ public class AbstractPlugin implements Plugin<Project> {
// add modsCompile to maven-publish // add modsCompile to maven-publish
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class); PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish != null) { if (mavenPublish != null) {
mavenPublish.publications((publications) -> { mavenPublish.publications((publications) -> {
for (Publication publication : publications) { for (Publication publication : publications) {
@ -393,15 +414,14 @@ public class AbstractPlugin implements Plugin<Project> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies"); Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>(); Set<String> foundArtifacts = new HashSet<>();
GroovyXmlUtil.childrenNodesStream(dependencies) GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> {
.filter((n) -> "dependency".equals(n.name())) Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
.forEach((n) -> { Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId");
Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId"); if (groupId.isPresent() && artifactId.isPresent()) {
if (groupId.isPresent() && artifactId.isPresent()) { foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text());
foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text()); }
} });
});
for (Dependency dependency : compileModsConfig.getAllDependencies()) { for (Dependency dependency : compileModsConfig.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) { if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {

View File

@ -24,28 +24,30 @@
package net.fabricmc.loom; package net.fabricmc.loom;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import net.fabricmc.loom.providers.MappingsProvider; import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider; import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider; import net.fabricmc.loom.providers.MinecraftProvider;
import net.fabricmc.loom.util.LoomDependencyManager; import net.fabricmc.loom.util.LoomDependencyManager;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.Project;
import org.gradle.api.UnknownDomainObjectException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.component.ComponentIdentifier;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import javax.annotation.Nullable;
import java.io.File;
import java.nio.file.Path;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;
public class LoomGradleExtension { public class LoomGradleExtension {
public String runDir = "run"; public String runDir = "run";
@ -87,77 +89,93 @@ public class LoomGradleExtension {
} }
public void setInstallerJson(JsonObject object, int priority) { public void setInstallerJson(JsonObject object, int priority) {
if (installerJson == null || priority <= installerJsonPriority) { if (installerJson == null || priority <= installerJsonPriority) {
this.installerJson = object; this.installerJson = object;
this.installerJsonPriority = priority; this.installerJsonPriority = priority;
} }
} }
public JsonObject getInstallerJson() { public JsonObject getInstallerJson() {
return installerJson; return installerJson;
} }
public File getUserCache() { public File getUserCache() {
File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom"); File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom");
if (!userCache.exists()) { if (!userCache.exists()) {
userCache.mkdirs(); userCache.mkdirs();
} }
return userCache; return userCache;
} }
public File getRootProjectPersistentCache() { public File getRootProjectPersistentCache() {
File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache"); File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs(); projectCache.mkdirs();
} }
return projectCache; return projectCache;
} }
public File getRootProjectBuildCache() { public File getRootProjectBuildCache() {
File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache"); File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs(); projectCache.mkdirs();
} }
return projectCache; return projectCache;
} }
public File getProjectBuildCache() { public File getProjectBuildCache() {
File projectCache = new File(project.getBuildDir(), "loom-cache"); File projectCache = new File(project.getBuildDir(), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs(); projectCache.mkdirs();
} }
return projectCache; return projectCache;
} }
public File getRemappedModCache() { public File getRemappedModCache() {
File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods"); File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods");
if (!remappedModCache.exists()) { if (!remappedModCache.exists()) {
remappedModCache.mkdir(); remappedModCache.mkdir();
} }
return remappedModCache; return remappedModCache;
} }
public File getNestedModCache() { public File getNestedModCache() {
File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods"); File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods");
if (!nestedModCache.exists()) { if (!nestedModCache.exists()) {
nestedModCache.mkdir(); nestedModCache.mkdir();
} }
return nestedModCache; return nestedModCache;
} }
public File getNativesJarStore(){ public File getNativesJarStore() {
File natives = new File(getUserCache(), "natives/jars"); File natives = new File(getUserCache(), "natives/jars");
if(!natives.exists()) {
if (!natives.exists()) {
natives.mkdirs(); natives.mkdirs();
} }
return natives; return natives;
} }
public File getNativesDirectory(){ public File getNativesDirectory() {
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion); File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion);
if(!natives.exists()) {
if (!natives.exists()) {
natives.mkdirs(); natives.mkdirs();
} }
return natives; return natives;
} }
@ -167,6 +185,7 @@ public class LoomGradleExtension {
for (Dependency dependency : config.getDependencies()) { for (Dependency dependency : config.getDependencies()) {
String group = dependency.getGroup(); String group = dependency.getGroup();
String name = dependency.getName(); String name = dependency.getName();
if (groupNameFilter.test(group, name)) { if (groupNameFilter.test(group, name)) {
p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion()); p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion());
return dependency; return dependency;
@ -181,12 +200,15 @@ public class LoomGradleExtension {
private <T> T recurseProjects(Function<Project, T> projectTFunction) { private <T> T recurseProjects(Function<Project, T> projectTFunction) {
Project p = this.project; Project p = this.project;
T result; T result;
while (!AbstractPlugin.isRootProject(p)) { while (!AbstractPlugin.isRootProject(p)) {
if ((result = projectTFunction.apply(p)) != null) { if ((result = projectTFunction.apply(p)) != null) {
return result; return result;
} }
p = p.getRootProject(); p = p.getRootProject();
} }
result = projectTFunction.apply(p); result = projectTFunction.apply(p);
return result; return result;
} }
@ -197,9 +219,11 @@ public class LoomGradleExtension {
List<Configuration> configs = new ArrayList<>(); List<Configuration> configs = new ArrayList<>();
// check compile classpath first // check compile classpath first
Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath");
if (possibleCompileClasspath != null) { if (possibleCompileClasspath != null) {
configs.add(possibleCompileClasspath); configs.add(possibleCompileClasspath);
} }
// failing that, buildscript // failing that, buildscript
configs.addAll(p.getBuildscript().getConfigurations()); configs.addAll(p.getBuildscript().getConfigurations());
@ -242,15 +266,15 @@ public class LoomGradleExtension {
return dependencyManager; return dependencyManager;
} }
public MinecraftProvider getMinecraftProvider(){ public MinecraftProvider getMinecraftProvider() {
return getDependencyManager().getProvider(MinecraftProvider.class); return getDependencyManager().getProvider(MinecraftProvider.class);
} }
public MinecraftMappedProvider getMinecraftMappedProvider(){ public MinecraftMappedProvider getMinecraftMappedProvider() {
return getMappingsProvider().mappedProvider; return getMappingsProvider().mappedProvider;
} }
public MappingsProvider getMappingsProvider(){ public MappingsProvider getMappingsProvider() {
return getDependencyManager().getProvider(MappingsProvider.class); return getDependencyManager().getProvider(MappingsProvider.class);
} }
@ -259,7 +283,7 @@ public class LoomGradleExtension {
} }
public String getRefmapName() { public String getRefmapName() {
if(refmapName == null || refmapName.isEmpty()){ if (refmapName == null || refmapName.isEmpty()) {
project.getLogger().warn("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json"); project.getLogger().warn("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json");
refmapName = project.getName() + "-refmap.json"; refmapName = project.getName() + "-refmap.json";
} }

View File

@ -24,26 +24,40 @@
package net.fabricmc.loom; package net.fabricmc.loom;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftLibraryProvider;
import net.fabricmc.loom.task.*;
import net.fabricmc.loom.task.fernflower.FernFlowerTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskContainer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Locale; import java.util.Locale;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskContainer;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftLibraryProvider;
import net.fabricmc.loom.task.AbstractDecompileTask;
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.MigrateMappingsTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.task.RemapLineNumbersTask;
import net.fabricmc.loom.task.RemapSourcesJarTask;
import net.fabricmc.loom.task.RunClientTask;
import net.fabricmc.loom.task.RunServerTask;
import net.fabricmc.loom.task.fernflower.FernFlowerTask;
public class LoomGradlePlugin extends AbstractPlugin { public class LoomGradlePlugin extends AbstractPlugin {
private static File getMappedByproduct(Project project, String suffix) { private static File getMappedByproduct(Project project, String suffix) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider(); MappingsProvider mappingsProvider = extension.getMappingsProvider();
File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath(); String path = mappedJar.getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) { if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {
throw new RuntimeException("Invalid mapped JAR path: " + path); throw new RuntimeException("Invalid mapped JAR path: " + path);
} }
@ -57,7 +71,6 @@ public class LoomGradlePlugin extends AbstractPlugin {
TaskContainer tasks = target.getTasks(); TaskContainer tasks = target.getTasks();
tasks.register("cleanLoomBinaries", CleanLoomBinaries.class); tasks.register("cleanLoomBinaries", CleanLoomBinaries.class);
tasks.register("cleanLoomMappings", CleanLoomMappings.class); tasks.register("cleanLoomMappings", CleanLoomMappings.class);

View File

@ -24,41 +24,42 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import net.fabricmc.loom.util.StaticPathWatcher;
import net.fabricmc.mappings.Mappings;
import org.gradle.api.logging.Logging;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.nio.file.*; import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.fabricmc.loom.util.StaticPathWatcher;
import net.fabricmc.mappings.Mappings;
public final class MappingsCache { public final class MappingsCache {
public static final MappingsCache INSTANCE = new MappingsCache(); public static final MappingsCache INSTANCE = new MappingsCache();
private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>();
public Mappings get(Path mappingsPath) { public Mappings get(Path mappingsPath) {
mappingsPath = mappingsPath.toAbsolutePath(); mappingsPath = mappingsPath.toAbsolutePath();
if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
mappingsCache.remove(mappingsPath);
}
SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
if (ref != null && ref.get() != null) { mappingsCache.remove(mappingsPath);
return ref.get(); }
} else {
try (InputStream stream = Files.newInputStream(mappingsPath)) { SoftReference<Mappings> ref = mappingsCache.get(mappingsPath);
Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
ref = new SoftReference<>(mappings); if (ref != null && ref.get() != null) {
mappingsCache.put(mappingsPath, ref); return ref.get();
return mappings; } else {
} catch (IOException e) { try (InputStream stream = Files.newInputStream(mappingsPath)) {
throw new RuntimeException(e); Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
} ref = new SoftReference<>(mappings);
} mappingsCache.put(mappingsPath, ref);
} return mappings;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
} }

View File

@ -24,23 +24,22 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider; import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.Version; import net.fabricmc.loom.util.Version;
import net.fabricmc.mappings.Mappings; import net.fabricmc.mappings.Mappings;
import net.fabricmc.stitch.commands.CommandProposeFieldNames; import net.fabricmc.stitch.commands.CommandProposeFieldNames;
import org.gradle.api.Project;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;
//TODO fix local mappings //TODO fix local mappings
//TODO possibly use maven for mappings, can fix above at the same time //TODO possibly use maven for mappings, can fix above at the same time
@ -84,6 +83,7 @@ public class MappingsProvider extends DependencyProvider {
if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) { if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) {
if (!MAPPINGS_TINY_BASE.exists()) { if (!MAPPINGS_TINY_BASE.exists()) {
project.getLogger().lifecycle(":extracting " + mappingsJar.getName()); project.getLogger().lifecycle(":extracting " + mappingsJar.getName());
try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) { try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) {
Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny"); Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny");
Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath()); Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath());
@ -95,11 +95,7 @@ public class MappingsProvider extends DependencyProvider {
} }
project.getLogger().lifecycle(":populating field names"); project.getLogger().lifecycle(":populating field names");
new CommandProposeFieldNames().run(new String[] { new CommandProposeFieldNames().run(new String[]{minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), MAPPINGS_TINY_BASE.getAbsolutePath(), MAPPINGS_TINY.getAbsolutePath()});
minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(),
MAPPINGS_TINY_BASE.getAbsolutePath(),
MAPPINGS_TINY.getAbsolutePath()
});
} }
mappedProvider = new MinecraftMappedProvider(); mappedProvider = new MinecraftMappedProvider();

View File

@ -24,7 +24,16 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Checksum; import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
@ -34,15 +43,6 @@ import net.fabricmc.loom.util.assets.AssetIndex;
import net.fabricmc.loom.util.assets.AssetObject; import net.fabricmc.loom.util.assets.AssetObject;
import net.fabricmc.loom.util.progress.ProgressLogger; import net.fabricmc.loom.util.progress.ProgressLogger;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
public class MinecraftAssetsProvider { public class MinecraftAssetsProvider {
public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
@ -53,13 +53,16 @@ public class MinecraftAssetsProvider {
// get existing cache files // get existing cache files
File assets = new File(extension.getUserCache(), "assets"); File assets = new File(extension.getUserCache(), "assets");
if (!assets.exists()) { if (!assets.exists()) {
assets.mkdirs(); assets.mkdirs();
} }
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json"); File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json");
if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) {
project.getLogger().lifecycle(":downloading asset index"); project.getLogger().lifecycle(":downloading asset index");
if (offline) { if (offline) {
if (assetsInfo.exists()) { if (assetsInfo.exists()) {
//We know it's outdated but can't do anything about it, oh well //We know it's outdated but can't do anything about it, oh well
@ -76,13 +79,16 @@ public class MinecraftAssetsProvider {
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName());
progressLogger.start("Downloading assets...", "assets"); progressLogger.start("Downloading assets...", "assets");
AssetIndex index; AssetIndex index;
try (FileReader fileReader = new FileReader(assetsInfo)) { try (FileReader fileReader = new FileReader(assetsInfo)) {
index = new Gson().fromJson(fileReader, AssetIndex.class); index = new Gson().fromJson(fileReader, AssetIndex.class);
} }
Map<String, AssetObject> parent = index.getFileMap(); Map<String, AssetObject> parent = index.getFileMap();
final int totalSize = parent.size(); final int totalSize = parent.size();
int position = 0; int position = 0;
project.getLogger().lifecycle(":downloading assets..."); project.getLogger().lifecycle(":downloading assets...");
for (Map.Entry<String, AssetObject> entry : parent.entrySet()) { for (Map.Entry<String, AssetObject> entry : parent.entrySet()) {
AssetObject object = entry.getValue(); AssetObject object = entry.getValue();
String sha1 = object.getHash(); String sha1 = object.getHash();
@ -101,11 +107,14 @@ public class MinecraftAssetsProvider {
DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true);
} }
} }
String assetName = entry.getKey(); String assetName = entry.getKey();
int end = assetName.lastIndexOf("/") + 1; int end = assetName.lastIndexOf("/") + 1;
if (end > 0) { if (end > 0) {
assetName = assetName.substring(end); assetName = assetName.substring(end);
} }
progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded"); progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded");
position++; position++;
} }

View File

@ -24,27 +24,18 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import com.google.gson.Gson;
import net.fabricmc.loom.LoomGradleExtension;
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 org.gradle.api.Project;
import java.io.File; import java.io.File;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.MinecraftVersionInfo;
public class MinecraftLibraryProvider { public class MinecraftLibraryProvider {
public File MINECRAFT_LIBS; public File MINECRAFT_LIBS;
private Collection<File> libs = new HashSet<>(); private Collection<File> libs = new HashSet<>();
@ -61,6 +52,7 @@ public class MinecraftLibraryProvider {
// By default, they are all available on all sides // By default, they are all available on all sides
/* boolean isClientOnly = false; /* boolean isClientOnly = false;
if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) { if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) {
isClientOnly = true; isClientOnly = true;
} */ } */
@ -78,5 +70,4 @@ public class MinecraftLibraryProvider {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries");
} }
} }

View File

@ -24,73 +24,76 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.MapJarsTiny;
import org.gradle.api.Project;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.Collection;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.MapJarsTiny;
public class MinecraftMappedProvider extends DependencyProvider { public class MinecraftMappedProvider extends DependencyProvider {
public File MINECRAFT_MAPPED_JAR; public File MINECRAFT_MAPPED_JAR;
public File MINECRAFT_INTERMEDIARY_JAR; public File MINECRAFT_INTERMEDIARY_JAR;
private MinecraftProvider minecraftProvider; private MinecraftProvider minecraftProvider;
@Override @Override
public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception {
if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) {
throw new RuntimeException("mappings file not found"); throw new RuntimeException("mappings file not found");
} }
if (!extension.getMinecraftProvider().getMergedJar().exists()) { if (!extension.getMinecraftProvider().getMergedJar().exists()) {
throw new RuntimeException("input merged jar not found"); throw new RuntimeException("input merged jar not found");
} }
if(!getMappedJar().exists() || !getIntermediaryJar().exists()){ if (!getMappedJar().exists() || !getIntermediaryJar().exists()) {
if (getMappedJar().exists()) { if (getMappedJar().exists()) {
getMappedJar().delete(); getMappedJar().delete();
} }
if (getIntermediaryJar().exists()) {
getIntermediaryJar().delete();
}
new MapJarsTiny().mapJars(minecraftProvider, this, project);
}
if (!MINECRAFT_MAPPED_JAR.exists()) { if (getIntermediaryJar().exists()) {
throw new RuntimeException("mapped jar not found"); getIntermediaryJar().delete();
} }
String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion; new MapJarsTiny().mapJars(minecraftProvider, this, project);
project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version)); }
version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName;
project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version));
}
public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { if (!MINECRAFT_MAPPED_JAR.exists()) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); throw new RuntimeException("mapped jar not found");
this.minecraftProvider = minecraftProvider; }
MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-" + mappingsProvider.mappingsName + ".jar");
MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar");
}
public Collection<File> getMapperPaths() { String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion;
return minecraftProvider.libraryProvider.getLibraries(); project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version));
} version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName;
project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version));
}
public File getIntermediaryJar() { public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
return MINECRAFT_INTERMEDIARY_JAR; LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
} this.minecraftProvider = minecraftProvider;
MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-" + mappingsProvider.mappingsName + ".jar");
MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar");
}
public File getMappedJar() { public Collection<File> getMapperPaths() {
return MINECRAFT_MAPPED_JAR; return minecraftProvider.libraryProvider.getLibraries();
} }
@Override public File getIntermediaryJar() {
public String getTargetConfig() { return MINECRAFT_INTERMEDIARY_JAR;
return Constants.MINECRAFT_NAMED; }
}
public File getMappedJar() {
return MINECRAFT_MAPPED_JAR;
}
@Override
public String getTargetConfig() {
return Constants.MINECRAFT_NAMED;
}
} }

View File

@ -24,18 +24,18 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import org.gradle.api.Project;
import org.zeroturnaround.zip.ZipUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
public class MinecraftNativesProvider { import org.zeroturnaround.zip.ZipUtil;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
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 { public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo; MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo;
@ -45,6 +45,7 @@ public class MinecraftNativesProvider {
for (MinecraftVersionInfo.Library library : versionInfo.libraries) { for (MinecraftVersionInfo.Library library : versionInfo.libraries) {
File libJarFile = library.getFile(jarStore); File libJarFile = library.getFile(jarStore);
if (library.allowed() && library.isNative() && libJarFile != null) { if (library.allowed() && library.isNative() && libJarFile != null) {
DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger()); DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger());
@ -53,5 +54,4 @@ public class MinecraftNativesProvider {
} }
} }
} }
} }

View File

@ -24,17 +24,6 @@
package net.fabricmc.loom.providers; package net.fabricmc.loom.providers;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.*;
import net.fabricmc.stitch.merge.JarMerger;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
@ -44,8 +33,24 @@ import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.zip.ZipError; import java.util.zip.ZipError;
public class MinecraftProvider extends DependencyProvider { import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Checksum;
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.stitch.merge.JarMerger;
public class MinecraftProvider extends DependencyProvider {
public String minecraftVersion; public String minecraftVersion;
public MinecraftVersionInfo versionInfo; public MinecraftVersionInfo versionInfo;
@ -66,25 +71,26 @@ public class MinecraftProvider extends DependencyProvider {
initFiles(project); initFiles(project);
downloadMcJson(project, offline); downloadMcJson(project, offline);
try (FileReader reader = new FileReader(MINECRAFT_JSON)) { try (FileReader reader = new FileReader(MINECRAFT_JSON)) {
versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class); versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class);
} }
// Add Loom as an annotation processor // Add Loom as an annotation processor
addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly"); addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly");
if (offline) { if (offline) {
if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) { if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) {
project.getLogger().debug("Found client and server jars, presuming up-to-date"); project.getLogger().debug("Found client and server jars, presuming up-to-date");
} else if (MINECRAFT_MERGED_JAR.exists()) { } else if (MINECRAFT_MERGED_JAR.exists()) {
//Strictly we don't need the split jars if the merged one exists, let's try go on //Strictly we don't need the split jars if the merged one exists, let's try go on
project.getLogger().warn("Missing game jar but merged jar present, things might end badly"); project.getLogger().warn("Missing game jar but merged jar present, things might end badly");
} else { } else {
throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists()); throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists());
} }
} else { } else {
downloadJars(project.getLogger()); downloadJars(project.getLogger());
} }
libraryProvider = new MinecraftLibraryProvider(); libraryProvider = new MinecraftLibraryProvider();
libraryProvider.provide(this, project); libraryProvider.provide(this, project);
@ -108,7 +114,6 @@ public class MinecraftProvider extends DependencyProvider {
MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
} }
private void downloadMcJson(Project project, boolean offline) throws IOException { private void downloadMcJson(Project project, boolean offline) throws IOException {
@ -135,7 +140,7 @@ public class MinecraftProvider extends DependencyProvider {
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
if(extension.customManifest != null){ if (extension.customManifest != null) {
ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
customVersion.id = minecraftVersion; customVersion.id = minecraftVersion;
customVersion.url = extension.customManifest; customVersion.url = extension.customManifest;
@ -143,7 +148,7 @@ public class MinecraftProvider extends DependencyProvider {
project.getLogger().lifecycle("Using custom minecraft manifest"); project.getLogger().lifecycle("Using custom minecraft manifest");
} }
if(!optionalVersion.isPresent()){ if (!optionalVersion.isPresent()) {
optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
} }
@ -165,7 +170,6 @@ public class MinecraftProvider extends DependencyProvider {
} else { } else {
throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion);
} }
} }
private void downloadJars(Logger logger) throws IOException { private void downloadJars(Logger logger) throws IOException {
@ -182,6 +186,7 @@ public class MinecraftProvider extends DependencyProvider {
private void mergeJars(Logger logger) throws IOException { private void mergeJars(Logger logger) throws IOException {
logger.lifecycle(":merging jars"); logger.lifecycle(":merging jars");
try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) { try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) {
jarMerger.enableSyntheticParamsOffset(); jarMerger.enableSyntheticParamsOffset();
jarMerger.merge(); jarMerger.merge();

View File

@ -24,29 +24,52 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import java.io.File;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import java.io.File;
public abstract class AbstractDecompileTask extends AbstractLoomTask { public abstract class AbstractDecompileTask extends AbstractLoomTask {
private Object input; private Object input;
private Object output; private Object output;
private Object lineMapFile; private Object lineMapFile;
private Object libraries; private Object libraries;
//@formatter:off @InputFile
@InputFile public File getInput() {
public File getInput() { return getProject().file(input); } return getProject().file(input);
@OutputFile public File getOutput() { return getProject().file(output); } }
@OutputFile public File getLineMapFile() { return getProject().file(lineMapFile); }
@InputFiles public FileCollection getLibraries() { return getProject().files(libraries); } @OutputFile
public void setInput(Object input) { this.input = input; } public File getOutput() {
public void setOutput(Object output) { this.output = output; } return getProject().file(output);
public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } }
public void setLibraries(Object libraries) { this.libraries = libraries; }
//@formatter:on @OutputFile
public File getLineMapFile() {
return getProject().file(lineMapFile);
}
@InputFiles
public FileCollection getLibraries() {
return getProject().files(libraries);
}
public void setInput(Object input) {
this.input = input;
}
public void setOutput(Object output) {
this.output = output;
}
public void setLineMapFile(Object lineMapFile) {
this.lineMapFile = lineMapFile;
}
public void setLibraries(Object libraries) {
this.libraries = libraries;
}
} }

View File

@ -27,9 +27,7 @@ package net.fabricmc.loom.task;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
public abstract class AbstractLoomTask extends DefaultTask { public abstract class AbstractLoomTask extends DefaultTask {
public AbstractLoomTask() { public AbstractLoomTask() {
setGroup("fabric"); setGroup("fabric");
} }
} }

View File

@ -24,14 +24,6 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import net.fabricmc.loom.util.OperatingSystem;
import net.fabricmc.loom.util.RunConfig;
import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -41,99 +33,113 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.MinecraftVersionInfo;
import net.fabricmc.loom.util.RunConfig;
public abstract class AbstractRunTask extends JavaExec { public abstract class AbstractRunTask extends JavaExec {
private final Function<Project, RunConfig> configProvider; private final Function<Project, RunConfig> configProvider;
private RunConfig config; private RunConfig config;
public AbstractRunTask(Function<Project, RunConfig> config) { public AbstractRunTask(Function<Project, RunConfig> config) {
super(); super();
setGroup("fabric"); setGroup("fabric");
this.configProvider = config; this.configProvider = config;
} }
@Override @Override
public void exec() { public void exec() {
if (config == null) { if (config == null) {
config = configProvider.apply(getProject()); config = configProvider.apply(getProject());
} }
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo; MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo;
MappingsProvider mappingsProvider = extension.getMappingsProvider(); MappingsProvider mappingsProvider = extension.getMappingsProvider();
List<String> libs = new ArrayList<>(); List<String> libs = new ArrayList<>();
for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) {
libs.add(file.getAbsolutePath());
}
for (Path file : extension.getUnmappedMods()) {
if (Files.isRegularFile(file)) {
libs.add(file.toFile().getAbsolutePath());
}
}
classpath(libs); for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) {
List<String> argsSplit = new ArrayList<>(); libs.add(file.getAbsolutePath());
String[] args = config.programArgs.split(" "); }
int partPos = -1;
for (int i = 0; i < args.length; i++) {
if (partPos < 0) {
if (args[i].startsWith("\"")) {
if (args[i].endsWith("\"")) {
argsSplit.add(args[i].substring(1, args[i].length() - 1));
} else {
partPos = i;
}
} else {
argsSplit.add(args[i]);
}
} else if (args[i].endsWith("\"")) {
StringBuilder builder = new StringBuilder(args[partPos].substring(1));
for (int j = partPos + 1; j < i; j++) {
builder.append(" ").append(args[j]);
}
builder.append(" ").append(args[i], 0, args[i].length() - 1);
argsSplit.add(builder.toString());
partPos = -1;
}
}
args(argsSplit); for (Path file : extension.getUnmappedMods()) {
setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); if (Files.isRegularFile(file)) {
libs.add(file.toFile().getAbsolutePath());
}
}
super.exec(); classpath(libs);
} List<String> argsSplit = new ArrayList<>();
String[] args = config.programArgs.split(" ");
int partPos = -1;
@Override for (int i = 0; i < args.length; i++) {
public void setWorkingDir(File dir) { if (partPos < 0) {
if (config == null) { if (args[i].startsWith("\"")) {
config = configProvider.apply(getProject()); if (args[i].endsWith("\"")) {
} argsSplit.add(args[i].substring(1, args[i].length() - 1));
} else {
partPos = i;
}
} else {
argsSplit.add(args[i]);
}
} else if (args[i].endsWith("\"")) {
StringBuilder builder = new StringBuilder(args[partPos].substring(1));
if(!dir.exists()){ for (int j = partPos + 1; j < i; j++) {
dir.mkdirs(); builder.append(" ").append(args[j]);
} }
super.setWorkingDir(dir);
}
@Override builder.append(" ").append(args[i], 0, args[i].length() - 1);
public String getMain() { argsSplit.add(builder.toString());
if (config == null) { partPos = -1;
config = configProvider.apply(getProject()); }
} }
return config.mainClass; args(argsSplit);
} setWorkingDir(new File(getProject().getRootDir(), extension.runDir));
@Override super.exec();
public List<String> getJvmArgs() { }
if (config == null) {
config = configProvider.apply(getProject()); @Override
} public void setWorkingDir(File dir) {
if (config == null) {
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); config = configProvider.apply(getProject());
List<String> superArgs = super.getJvmArgs(); }
List<String> args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList());
args.addAll(Arrays.asList(config.vmArgs.split(" "))); if (!dir.exists()) {
return args; dir.mkdirs();
} }
super.setWorkingDir(dir);
}
@Override
public String getMain() {
if (config == null) {
config = configProvider.apply(getProject());
}
return config.mainClass;
}
@Override
public List<String> getJvmArgs() {
if (config == null) {
config = configProvider.apply(getProject());
}
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
List<String> superArgs = super.getJvmArgs();
List<String> args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList());
args.addAll(Arrays.asList(config.vmArgs.split(" ")));
return args;
}
} }

View File

@ -24,26 +24,28 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension; import java.io.IOException;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import java.io.IOException; import net.fabricmc.loom.LoomGradleExtension;
public class CleanLoomBinaries extends AbstractLoomTask { public class CleanLoomBinaries extends AbstractLoomTask {
@TaskAction @TaskAction
public void run() { public void run() {
Project project = this.getProject(); Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMinecraftProvider().getMergedJar().delete(); extension.getMinecraftProvider().getMergedJar().delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete(); extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
FileUtils.deleteDirectory(extension.getNativesDirectory()); try {
FileUtils.deleteDirectory(extension.getNativesJarStore()); FileUtils.deleteDirectory(extension.getNativesDirectory());
} catch (IOException e) { FileUtils.deleteDirectory(extension.getNativesJarStore());
e.printStackTrace(); } catch (IOException e) {
} e.printStackTrace();
} }
}
} }

View File

@ -24,27 +24,29 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DeletingFileVisitor;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DeletingFileVisitor;
public class CleanLoomMappings extends AbstractLoomTask { public class CleanLoomMappings extends AbstractLoomTask {
@TaskAction @TaskAction
public void run() { public void run() {
Project project = this.getProject(); Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMappingsProvider().MAPPINGS_TINY.delete(); extension.getMappingsProvider().MAPPINGS_TINY.delete();
extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete(); extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete(); extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); try {
} catch (IOException e) { Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor());
throw new RuntimeException(e); } catch (IOException e) {
} throw new RuntimeException(e);
} }
}
} }

View File

@ -24,13 +24,14 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension; import java.io.IOException;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import java.io.IOException; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
public class DownloadAssetsTask extends AbstractLoomTask { public class DownloadAssetsTask extends AbstractLoomTask {
@TaskAction @TaskAction

View File

@ -36,18 +36,18 @@ import org.gradle.process.JavaExecSpec;
* Simple trait like interface for a Task that wishes to execute a java process * Simple trait like interface for a Task that wishes to execute a java process
* with the classpath of the gradle plugin plus groovy. * with the classpath of the gradle plugin plus groovy.
* *
* Created by covers1624 on 11/02/19. * <p>Created by covers1624 on 11/02/19.
*/ */
public interface ForkingJavaExecTask extends Task { public interface ForkingJavaExecTask extends Task {
default ExecResult javaexec(Action<? super JavaExecSpec> action) {
ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations();
DependencyHandler handler = getProject().getDependencies();
FileCollection classpath = configurations.getByName("classpath")//
.plus(configurations.detachedConfiguration(handler.localGroovy()));
default ExecResult javaexec(Action<? super JavaExecSpec> action) { return getProject().javaexec(spec -> {
ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations(); spec.classpath(classpath);
DependencyHandler handler = getProject().getDependencies(); action.execute(spec);
FileCollection classpath = configurations.getByName("classpath")// });
.plus(configurations.detachedConfiguration(handler.localGroovy())); }
return getProject().javaexec(spec -> {
spec.classpath(classpath);
action.execute(spec);
});
}
} }

View File

@ -24,33 +24,37 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
public class GenEclipseRunsTask extends AbstractLoomTask { public class GenEclipseRunsTask extends AbstractLoomTask {
@TaskAction
public void genRuns() throws IOException {
File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch");
File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch");
@TaskAction String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
public void genRuns() throws IOException { String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch");
File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch");
String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); if (!clientRunConfigs.exists()) {
String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8);
}
if(!clientRunConfigs.exists()) if (!serverRunConfigs.exists()) {
FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8);
if(!serverRunConfigs.exists()) }
FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8);
File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir); File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir);
if(!runDir.exists())
runDir.mkdirs();
}
if (!runDir.exists()) {
runDir.mkdirs();
}
}
} }

View File

@ -24,15 +24,8 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.AbstractPlugin; import java.io.File;
import net.fabricmc.loom.LoomGradleExtension; import java.io.IOException;
import net.fabricmc.loom.util.RunConfig;
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 javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -43,18 +36,28 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException; 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;
public class GenIdeaProjectTask extends AbstractLoomTask { public class GenIdeaProjectTask extends AbstractLoomTask {
@TaskAction @TaskAction
public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException {
Project project = this.getProject(); Project project = this.getProject();
//Only generate the idea runs on the root project //Only generate the idea runs on the root project
if(!AbstractPlugin.isRootProject(project)){ if (!AbstractPlugin.isRootProject(project)) {
return; return;
} }
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
project.getLogger().lifecycle(":Building idea workspace"); project.getLogger().lifecycle(":Building idea workspace");
@ -65,8 +68,10 @@ public class GenIdeaProjectTask extends AbstractLoomTask {
NodeList list = doc.getElementsByTagName("component"); NodeList list = doc.getElementsByTagName("component");
Element runManager = null; Element runManager = null;
for (int i = 0; i < list.getLength(); i++) { for (int i = 0; i < list.getLength(); i++) {
Element element = (Element) list.item(i); Element element = (Element) list.item(i);
if (element.getAttribute("name").equals("RunManager")) { if (element.getAttribute("name").equals("RunManager")) {
runManager = element; runManager = element;
break; break;
@ -89,6 +94,7 @@ public class GenIdeaProjectTask extends AbstractLoomTask {
transformer.transform(source, result); transformer.transform(source, result);
File runDir = new File(getProject().getRootDir(), extension.runDir); File runDir = new File(getProject().getRootDir(), extension.runDir);
if (!runDir.exists()) { if (!runDir.exists()) {
runDir.mkdirs(); runDir.mkdirs();
} }

View File

@ -24,81 +24,85 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.RunConfig;
//Recommended vscode plugins: //Recommended vscode plugins:
// https://marketplace.visualstudio.com/items?itemName=redhat.java // https://marketplace.visualstudio.com/items?itemName=redhat.java
// https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug
// https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack
public class GenVsCodeProjectTask extends AbstractLoomTask { public class GenVsCodeProjectTask extends AbstractLoomTask {
@TaskAction
public void genRuns() {
LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class);
File projectDir = getProject().file(".vscode");
@TaskAction if (!projectDir.exists()) {
public void genRuns() { projectDir.mkdir();
LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); }
File projectDir = getProject().file(".vscode");
if (!projectDir.exists()) {
projectDir.mkdir();
}
File launchJson = new File(projectDir, "launch.json");
if (launchJson.exists()) {
launchJson.delete();
}
VsCodeLaunch launch = new VsCodeLaunch(); File launchJson = new File(projectDir, "launch.json");
launch.add(RunConfig.clientRunConfig(getProject()));
launch.add(RunConfig.serverRunConfig(getProject()));
Gson gson = new GsonBuilder().setPrettyPrinting().create(); if (launchJson.exists()) {
String json = gson.toJson(launch); launchJson.delete();
}
try { VsCodeLaunch launch = new VsCodeLaunch();
FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); launch.add(RunConfig.clientRunConfig(getProject()));
} catch (IOException e) { launch.add(RunConfig.serverRunConfig(getProject()));
throw new RuntimeException("Failed to write launch.json", e);
}
File runDir = new File(getProject().getRootDir(), extension.runDir); Gson gson = new GsonBuilder().setPrettyPrinting().create();
if (!runDir.exists()) { String json = gson.toJson(launch);
runDir.mkdirs();
}
}
private static class VsCodeLaunch { try {
public String version = "0.2.0"; FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8);
public List<VsCodeConfiguration> configurations = new ArrayList<>(); } catch (IOException e) {
throw new RuntimeException("Failed to write launch.json", e);
}
public void add(RunConfig runConfig) { File runDir = new File(getProject().getRootDir(), extension.runDir);
configurations.add(new VsCodeConfiguration(runConfig));
}
}
private static class VsCodeConfiguration { if (!runDir.exists()) {
public String type = "java"; runDir.mkdirs();
public String name; }
public String request = "launch"; }
public String cwd = "${workspaceFolder}/run";
public String console = "internalConsole";
public boolean stopOnEntry = false;
public String mainClass;
public String vmArgs;
public String args;
public VsCodeConfiguration(RunConfig runConfig) { private static class VsCodeLaunch {
this.name = runConfig.configName; public String version = "0.2.0";
this.mainClass = runConfig.mainClass; public List<VsCodeConfiguration> configurations = new ArrayList<>();
this.vmArgs = runConfig.vmArgs;
this.args = runConfig.programArgs; public void add(RunConfig runConfig) {
} configurations.add(new VsCodeConfiguration(runConfig));
} }
}
private static class VsCodeConfiguration {
public String type = "java";
public String name;
public String request = "launch";
public String cwd = "${workspaceFolder}/run";
public String console = "internalConsole";
public boolean stopOnEntry = false;
public String mainClass;
public String vmArgs;
public String args;
VsCodeConfiguration(RunConfig runConfig) {
this.name = runConfig.configName;
this.mainClass = runConfig.mainClass;
this.vmArgs = runConfig.vmArgs;
this.args = runConfig.programArgs;
}
}
} }

View File

@ -24,10 +24,12 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension; import java.io.File;
import net.fabricmc.loom.util.Constants; import java.io.FileInputStream;
import net.fabricmc.loom.util.Version; import java.io.IOException;
import net.fabricmc.mappings.*; import java.util.HashMap;
import java.util.Map;
import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.MappingsReader; import org.cadixdev.lorenz.io.MappingsReader;
import org.cadixdev.mercury.Mercury; import org.cadixdev.mercury.Mercury;
@ -35,149 +37,147 @@ import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import java.io.File; import net.fabricmc.loom.LoomGradleExtension;
import java.io.FileInputStream; import net.fabricmc.loom.util.Constants;
import java.io.IOException; import net.fabricmc.loom.util.Version;
import java.util.HashMap; import net.fabricmc.mappings.ClassEntry;
import java.util.Map; import net.fabricmc.mappings.EntryTriple;
import net.fabricmc.mappings.FieldEntry;
import net.fabricmc.mappings.Mappings;
import net.fabricmc.mappings.MethodEntry;
public class MigrateMappingsTask extends AbstractLoomTask { public class MigrateMappingsTask extends AbstractLoomTask {
@TaskAction @TaskAction
public void doTask() throws Throwable { public void doTask() throws Throwable {
Project project = getProject(); Project project = getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
Map<String, ?> properties = project.getProperties(); Map<String, ?> properties = project.getProperties();
project.getLogger().lifecycle(":loading mappings"); project.getLogger().lifecycle(":loading mappings");
File mappingsFile = null; File mappingsFile = null;
if (properties.containsKey("targetMappingsFile")) { if (properties.containsKey("targetMappingsFile")) {
mappingsFile = new File((String) properties.get("targetMappingsFile")); mappingsFile = new File((String) properties.get("targetMappingsFile"));
} else if (properties.containsKey("targetMappingsArtifact")) { } else if (properties.containsKey("targetMappingsArtifact")) {
String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":"); String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":");
if (artifactName.length != 3) {
throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact"));
}
String mappingsName = artifactName[0] + "." + artifactName[1]; if (artifactName.length != 3) {
throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact"));
}
Version v = new Version(artifactName[2]); String mappingsName = artifactName[0] + "." + artifactName[1];
String minecraftVersion = v.getMinecraftVersion();
String mappingsVersion = v.getMappingsVersion();
mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion); Version v = new Version(artifactName[2]);
} String minecraftVersion = v.getMinecraftVersion();
String mappingsVersion = v.getMappingsVersion();
if (mappingsFile == null || !mappingsFile.exists()) { mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion);
throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null")); }
}
if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) { if (mappingsFile == null || !mappingsFile.exists()) {
throw new RuntimeException("Must specify input and output dir!"); throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null"));
} }
File inputDir = new File((String) properties.get("inputDir")); if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) {
File outputDir = new File((String) properties.get("outputDir")); throw new RuntimeException("Must specify input and output dir!");
}
if (!inputDir.exists() || !inputDir.isDirectory()) { File inputDir = new File((String) properties.get("inputDir"));
throw new RuntimeException("Could not find input directory: " + inputDir); File outputDir = new File((String) properties.get("outputDir"));
}
if (!outputDir.exists()) { if (!inputDir.exists() || !inputDir.isDirectory()) {
if (!outputDir.mkdirs()) { throw new RuntimeException("Could not find input directory: " + inputDir);
throw new RuntimeException("Could not create output directory:" + outputDir); }
}
}
Mappings sourceMappings = extension.getMappingsProvider().getMappings(); if (!outputDir.exists()) {
Mappings targetMappings; if (!outputDir.mkdirs()) {
throw new RuntimeException("Could not create output directory:" + outputDir);
}
}
try (FileInputStream stream = new FileInputStream(mappingsFile)) { Mappings sourceMappings = extension.getMappingsProvider().getMappings();
targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); Mappings targetMappings;
}
project.getLogger().lifecycle(":joining mappings"); try (FileInputStream stream = new FileInputStream(mappingsFile)) {
MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read(); targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
}
project.getLogger().lifecycle(":remapping"); project.getLogger().lifecycle(":joining mappings");
Mercury mercury = new Mercury(); MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read();
for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { project.getLogger().lifecycle(":remapping");
mercury.getClassPath().add(file.toPath()); Mercury mercury = new Mercury();
}
for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
mercury.getClassPath().add(file.toPath()); mercury.getClassPath().add(file.toPath());
} }
mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath()); for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath()); mercury.getClassPath().add(file.toPath());
}
mercury.getProcessors().add(MercuryRemapper.create(mappingSet)); mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath());
mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath());
try { mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
mercury.rewrite(inputDir.toPath(), outputDir.toPath());
} catch (Exception e) {
project.getLogger().warn("Could not remap fully!", e);
}
project.getLogger().lifecycle(":cleaning file descriptors"); try {
System.gc(); mercury.rewrite(inputDir.toPath(), outputDir.toPath());
} } catch (Exception e) {
project.getLogger().warn("Could not remap fully!", e);
}
public static class MappingsJoiner extends MappingsReader { project.getLogger().lifecycle(":cleaning file descriptors");
private final Mappings sourceMappings, targetMappings; System.gc();
private final String fromNamespace, toNamespace; }
public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) { public static class MappingsJoiner extends MappingsReader {
this.sourceMappings = sourceMappings; private final Mappings sourceMappings, targetMappings;
this.targetMappings = targetMappings; private final String fromNamespace, toNamespace;
this.fromNamespace = fromNamespace;
this.toNamespace = toNamespace;
}
@Override public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) {
public MappingSet read(MappingSet mappings) throws IOException { this.sourceMappings = sourceMappings;
Map<String, ClassEntry> targetClasses = new HashMap<>(); this.targetMappings = targetMappings;
Map<EntryTriple, FieldEntry> targetFields = new HashMap<>(); this.fromNamespace = fromNamespace;
Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>(); this.toNamespace = toNamespace;
}
targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c)); @Override
targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c)); public MappingSet read(MappingSet mappings) throws IOException {
targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c)); Map<String, ClassEntry> targetClasses = new HashMap<>();
Map<EntryTriple, FieldEntry> targetFields = new HashMap<>();
Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>();
for (ClassEntry entry : sourceMappings.getClassEntries()) { targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c));
String from = entry.get(toNamespace); targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c));
String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c));
mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to); for (ClassEntry entry : sourceMappings.getClassEntries()) {
} String from = entry.get(toNamespace);
String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
for (FieldEntry entry : sourceMappings.getFieldEntries()) { mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to);
EntryTriple fromEntry = entry.get(toNamespace); }
EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
mappings.getOrCreateClassMapping(fromEntry.getOwner()) for (FieldEntry entry : sourceMappings.getFieldEntries()) {
.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()) EntryTriple fromEntry = entry.get(toNamespace);
.setDeobfuscatedName(toEntry.getName()); EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
}
for (MethodEntry entry : sourceMappings.getMethodEntries()) { mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
EntryTriple fromEntry = entry.get(toNamespace); }
EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
mappings.getOrCreateClassMapping(fromEntry.getOwner()) for (MethodEntry entry : sourceMappings.getMethodEntries()) {
.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()) EntryTriple fromEntry = entry.get(toNamespace);
.setDeobfuscatedName(toEntry.getName()); EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
}
return mappings; mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
} }
@Override return mappings;
public void close() throws IOException { }
} @Override
} public void close() throws IOException { }
}
} }

View File

@ -24,6 +24,21 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Set;
import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.jvm.tasks.Jar;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider; import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.GradleSupport; import net.fabricmc.loom.util.GradleSupport;
@ -33,21 +48,6 @@ import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils; import net.fabricmc.tinyremapper.TinyUtils;
import org.gradle.api.Project;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.jvm.tasks.Jar;
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Set;
public class RemapJarTask extends Jar { public class RemapJarTask extends Jar {
private RegularFileProperty input; private RegularFileProperty input;
@ -86,6 +86,7 @@ public class RemapJarTask extends Jar {
TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper(); TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)); remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM));
if (mixinMapFile.exists()) { if (mixinMapFile.exists()) {
remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM)); remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM));
} }
@ -93,9 +94,11 @@ public class RemapJarTask extends Jar {
project.getLogger().lifecycle(":remapping " + input.getFileName()); project.getLogger().lifecycle(":remapping " + input.getFileName());
StringBuilder rc = new StringBuilder("Remap classpath: "); StringBuilder rc = new StringBuilder("Remap classpath: ");
for (Path p : classpath) { for (Path p : classpath) {
rc.append("\n - ").append(p.toString()); rc.append("\n - ").append(p.toString());
} }
project.getLogger().debug(rc.toString()); project.getLogger().debug(rc.toString());
TinyRemapper remapper = remapperBuilder.build(); TinyRemapper remapper = remapperBuilder.build();

View File

@ -24,51 +24,68 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.task.fernflower.FernFlowerTask; import java.io.File;
import net.fabricmc.loom.util.LineNumberRemapper; import java.io.IOException;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.stitch.util.StitchUtil;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import java.io.File; import net.fabricmc.loom.task.fernflower.FernFlowerTask;
import java.io.IOException; import net.fabricmc.loom.util.LineNumberRemapper;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.stitch.util.StitchUtil;
public class RemapLineNumbersTask extends AbstractLoomTask { public class RemapLineNumbersTask extends AbstractLoomTask {
private Object input; private Object input;
private Object output; private Object output;
private Object lineMapFile; private Object lineMapFile;
@TaskAction @TaskAction
public void doTask() throws Throwable { public void doTask() throws Throwable {
Project project = getProject(); Project project = getProject();
project.getLogger().lifecycle(":adjusting line numbers"); project.getLogger().lifecycle(":adjusting line numbers");
LineNumberRemapper remapper = new LineNumberRemapper(); LineNumberRemapper remapper = new LineNumberRemapper();
remapper.readMappings(getLineMapFile()); remapper.readMappings(getLineMapFile());
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName()); ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName());
progressLogger.start("Adjusting line numbers", "linemap"); progressLogger.start("Adjusting line numbers", "linemap");
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) {
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) { remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/"));
remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); } catch (IOException e) {
} catch (IOException e) { throw new RuntimeException(e);
throw new RuntimeException(e); }
}
progressLogger.completed(); progressLogger.completed();
} }
//@formatter:off @InputFile
@InputFile public File getInput() { return getProject().file(input); } public File getInput() {
@InputFile public File getLineMapFile() { return getProject().file(lineMapFile); } return getProject().file(input);
@OutputFile public File getOutput() { return getProject().file(output); } }
public void setInput(Object input) { this.input = input; }
public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } @InputFile
public void setOutput(Object output) { this.output = output; } public File getLineMapFile() {
//@formatter:on return getProject().file(lineMapFile);
}
@OutputFile
public File getOutput() {
return getProject().file(output);
}
public void setInput(Object input) {
this.input = input;
}
public void setLineMapFile(Object lineMapFile) {
this.lineMapFile = lineMapFile;
}
public void setOutput(Object output) {
this.output = output;
}
} }

View File

@ -24,13 +24,14 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.util.SourceRemapper; import java.io.File;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import java.io.File; import net.fabricmc.loom.util.SourceRemapper;
public class RemapSourcesJarTask extends AbstractLoomTask { public class RemapSourcesJarTask extends AbstractLoomTask {
private Object input; private Object input;
@ -42,13 +43,30 @@ public class RemapSourcesJarTask extends AbstractLoomTask {
SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named"));
} }
//@formatter:off
@InputFile @InputFile
public File getInput() { return getProject().file(input); } public File getInput() {
@OutputFile public File getOutput() { return getProject().file(output == null ? input : output); } return getProject().file(input);
@Input public String getTargetNamespace() { return direction; } }
public void setInput(Object input) { this.input = input; }
public void setOutput(Object output) { this.output = output; } @OutputFile
public void setTargetNamespace(String value) { this.direction = value; } public File getOutput() {
//@formatter:on return getProject().file(output == null ? input : output);
}
@Input
public String getTargetNamespace() {
return direction;
}
public void setInput(Object input) {
this.input = input;
}
public void setOutput(Object output) {
this.output = output;
}
public void setTargetNamespace(String value) {
this.direction = value;
}
} }

View File

@ -24,123 +24,140 @@
package net.fabricmc.loom.task.fernflower; package net.fabricmc.loom.task.fernflower;
import net.fabricmc.loom.task.AbstractDecompileTask; import static java.text.MessageFormat.format;
import net.fabricmc.loom.task.ForkingJavaExecTask;
import net.fabricmc.loom.util.ConsumingOutputStream; import java.util.ArrayList;
import org.gradle.api.file.FileCollection; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.function.Supplier;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.LogLevel;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.logging.progress.ProgressLogger; import org.gradle.internal.logging.progress.ProgressLogger;
import org.gradle.internal.logging.progress.ProgressLoggerFactory; import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.internal.service.ServiceRegistry; import org.gradle.internal.service.ServiceRegistry;
import org.gradle.process.ExecResult; import org.gradle.process.ExecResult;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import java.io.File; import net.fabricmc.loom.task.AbstractDecompileTask;
import net.fabricmc.loom.task.ForkingJavaExecTask;
import net.fabricmc.loom.util.ConsumingOutputStream;
import net.fabricmc.loom.util.OperatingSystem; import net.fabricmc.loom.util.OperatingSystem;
import java.util.*;
import java.util.function.Supplier;
import static java.text.MessageFormat.format;
/** /**
* Created by covers1624 on 9/02/19. * Created by covers1624 on 9/02/19.
*/ */
public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask { public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask {
private boolean noFork = false;
private int numThreads = Runtime.getRuntime().availableProcessors();
private boolean noFork = false; @TaskAction
private int numThreads = Runtime.getRuntime().availableProcessors(); public void doTask() throws Throwable {
if (!OperatingSystem.is64Bit()) {
throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements");
}
@TaskAction Map<String, Object> options = new HashMap<>();
public void doTask() throws Throwable { options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1");
if(!OperatingSystem.is64Bit()){ options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1");
throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements"); options.put(IFernflowerPreferences.LOG_LEVEL, "trace");
} getLogging().captureStandardOutput(LogLevel.LIFECYCLE);
Map<String, Object> options = new HashMap<>(); List<String> args = new ArrayList<>();
options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1");
options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1");
options.put(IFernflowerPreferences.LOG_LEVEL, "trace");
getLogging().captureStandardOutput(LogLevel.LIFECYCLE);
List<String> args = new ArrayList<>(); options.forEach((k, v) -> args.add(format("-{0}={1}", k, v)));
args.add(getInput().getAbsolutePath());
args.add("-o=" + getOutput().getAbsolutePath());
options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); if (getLineMapFile() != null) {
args.add(getInput().getAbsolutePath()); args.add("-l=" + getLineMapFile().getAbsolutePath());
args.add("-o=" + getOutput().getAbsolutePath()); }
if (getLineMapFile() != null) {
args.add("-l=" + getLineMapFile().getAbsolutePath());
}
args.add("-t=" + getNumThreads());
//TODO, Decompiler breaks on jemalloc, J9 module-info.class? args.add("-t=" + getNumThreads());
getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath()));
ServiceRegistry registry = ((ProjectInternal) getProject()).getServices(); //TODO, Decompiler breaks on jemalloc, J9 module-info.class?
ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath()));
ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile");
Supplier<ProgressLogger> loggerFactory = () -> {
ProgressLogger pl = factory.newOperation(getClass(), progressGroup);
pl.setDescription("decompile worker");
pl.started();
return pl;
};
Stack<ProgressLogger> freeLoggers = new Stack<>();
Map<String, ProgressLogger> inUseLoggers = new HashMap<>();
progressGroup.started(); ServiceRegistry registry = ((ProjectInternal) getProject()).getServices();
ExecResult result = javaexec(spec -> { ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class);
spec.setMain(ForkedFFExecutor.class.getName()); ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile");
spec.jvmArgs("-Xms200m", "-Xmx3G"); Supplier<ProgressLogger> loggerFactory = () -> {
spec.setArgs(args); ProgressLogger pl = factory.newOperation(getClass(), progressGroup);
spec.setErrorOutput(System.err); pl.setDescription("decompile worker");
spec.setStandardOutput(new ConsumingOutputStream(line -> { pl.started();
if (line.startsWith("Listening for transport") || !line.contains("::")) { return pl;
System.out.println(line); };
return; Stack<ProgressLogger> freeLoggers = new Stack<>();
} Map<String, ProgressLogger> inUseLoggers = new HashMap<>();
int sepIdx = line.indexOf("::"); progressGroup.started();
String id = line.substring(0, sepIdx).trim(); ExecResult result = javaexec(spec -> {
String data = line.substring(sepIdx + 2).trim(); spec.setMain(ForkedFFExecutor.class.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;
}
ProgressLogger logger = inUseLoggers.get(id); int sepIdx = line.indexOf("::");
String id = line.substring(0, sepIdx).trim();
String data = line.substring(sepIdx + 2).trim();
String[] segs = data.split(" "); ProgressLogger logger = inUseLoggers.get(id);
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();
result.rethrowFailure(); String[] segs = data.split(" ");
result.assertNormalExitValue();
}
//@formatter:off if (segs[0].equals("waiting")) {
@Input public int getNumThreads() { return numThreads; } if (logger != null) {
@Input public boolean isNoFork() { return noFork; } logger.progress("Idle..");
public void setNoFork(boolean noFork) { this.noFork = noFork; } inUseLoggers.remove(id);
public void setNumThreads(int numThreads) { this.numThreads = numThreads; } freeLoggers.push(logger);
//@formatter:on }
} 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();
result.rethrowFailure();
result.assertNormalExitValue();
}
@Input
public int getNumThreads() {
return numThreads;
}
@Input
public boolean isNoFork() {
return noFork;
}
public void setNoFork(boolean noFork) {
this.noFork = noFork;
}
public void setNumThreads(int numThreads) {
this.numThreads = numThreads;
}
} }

View File

@ -24,26 +24,29 @@
package net.fabricmc.loom.task.fernflower; package net.fabricmc.loom.task.fernflower;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class FernFlowerUtils { public class FernFlowerUtils {
public static byte[] getBytecode(String externalPath, String internalPath) throws IOException { public static byte[] getBytecode(String externalPath, String internalPath) throws IOException {
File file = new File(externalPath); File file = new File(externalPath);
if (internalPath == null) {
return InterpreterUtil.getBytes(file); if (internalPath == null) {
} else { return InterpreterUtil.getBytes(file);
try (ZipFile archive = new ZipFile(file)) { } else {
ZipEntry entry = archive.getEntry(internalPath); try (ZipFile archive = new ZipFile(file)) {
if (entry == null) { ZipEntry entry = archive.getEntry(internalPath);
throw new IOException("Entry not found: " + internalPath);
} if (entry == null) {
return InterpreterUtil.getBytes(archive, entry); throw new IOException("Entry not found: " + internalPath);
} }
}
return InterpreterUtil.getBytes(archive, entry);
}
}
} }
} }

View File

@ -24,82 +24,92 @@
package net.fabricmc.loom.task.fernflower; package net.fabricmc.loom.task.fernflower;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.jetbrains.java.decompiler.main.Fernflower; import org.jetbrains.java.decompiler.main.Fernflower;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IResultSaver; import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import java.io.File;
import java.io.IOException;
import java.util.*;
/** /**
* Entry point for Forked FernFlower task. * Entry point for Forked FernFlower task.
* Takes one parameter, a single file, each line is treated as command line input. * Takes one parameter, a single file, each line is treated as command line input.
* Forces one input file. * Forces one input file.
* Forces one output file using '-o=/path/to/output' * Forces one output file using '-o=/path/to/output'
*
* Created by covers1624 on 11/02/19. * Created by covers1624 on 11/02/19.
*/ */
public class ForkedFFExecutor { public class ForkedFFExecutor {
public static void main(String[] args) throws IOException {
Map<String, Object> options = new HashMap<>();
File input = null;
File output = null;
File lineMap = null;
List<File> libraries = new ArrayList<>();
int numThreads = 0;
public static void main(String[] args) throws IOException { boolean isOption = true;
Map<String, Object> options = new HashMap<>();
File input = null;
File output = null;
File lineMap = null;
List<File> libraries = new ArrayList<>();
int numThreads = 0;
boolean isOption = true; for (String arg : args) {
for (String arg : args) { if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') {
if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { String value = arg.substring(5);
String value = arg.substring(5);
if ("true".equalsIgnoreCase(value)) {
value = "1";
} else if ("false".equalsIgnoreCase(value)) {
value = "0";
}
options.put(arg.substring(1, 4), value); if ("true".equalsIgnoreCase(value)) {
} else { value = "1";
isOption = false; } else if ("false".equalsIgnoreCase(value)) {
if (arg.startsWith("-e=")) { value = "0";
libraries.add(new File(arg.substring(3))); }
} else if (arg.startsWith("-o=")) {
if (output != null) {
throw new RuntimeException("Unable to set more than one output.");
}
output = new File(arg.substring(3));
} else if (arg.startsWith("-l=")) {
if (lineMap != null) {
throw new RuntimeException("Unable to set more than one lineMap file.");
}
lineMap = new File(arg.substring(3));
} else if (arg.startsWith("-t=")) {
numThreads = Integer.parseInt(arg.substring(3));
} else {
if (input != null) {
throw new RuntimeException("Unable to set more than one input.");
}
input = new File(arg);
}
}
}
Objects.requireNonNull(input, "Input not set."); options.put(arg.substring(1, 4), value);
Objects.requireNonNull(output, "Output not set."); } else {
isOption = false;
runFF(options, libraries, input, output, lineMap); if (arg.startsWith("-e=")) {
} libraries.add(new File(arg.substring(3)));
} else if (arg.startsWith("-o=")) {
if (output != null) {
throw new RuntimeException("Unable to set more than one output.");
}
public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) { output = new File(arg.substring(3));
IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); } else if (arg.startsWith("-l=")) {
IFernflowerLogger logger = new ThreadIDFFLogger(); if (lineMap != null) {
Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); throw new RuntimeException("Unable to set more than one lineMap file.");
for (File library : libraries) { }
ff.addLibrary(library);
} lineMap = new File(arg.substring(3));
ff.addSource(input); } else if (arg.startsWith("-t=")) {
ff.decompileContext(); numThreads = Integer.parseInt(arg.substring(3));
} } else {
if (input != null) {
throw new RuntimeException("Unable to set more than one input.");
}
input = new File(arg);
}
}
}
Objects.requireNonNull(input, "Input not set.");
Objects.requireNonNull(output, "Output not set.");
runFF(options, libraries, input, output, lineMap);
}
public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) {
IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap);
IFernflowerLogger logger = new ThreadIDFFLogger();
Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger);
for (File library : libraries) {
ff.addLibrary(library);
}
ff.addSource(input);
ff.decompileContext();
}
} }

View File

@ -31,14 +31,9 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
* Created by covers1624 on 11/02/19. * Created by covers1624 on 11/02/19.
*/ */
public class NoopFFLogger extends IFernflowerLogger { public class NoopFFLogger extends IFernflowerLogger {
@Override
public void writeMessage(String message, Severity severity) { }
@Override @Override
public void writeMessage(String message, Severity severity) { public void writeMessage(String message, Severity severity, Throwable t) { }
}
@Override
public void writeMessage(String message, Severity severity, Throwable t) {
}
} }

View File

@ -24,108 +24,108 @@
package net.fabricmc.loom.task.fernflower; package net.fabricmc.loom.task.fernflower;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import java.io.PrintStream; import java.io.PrintStream;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Stack; import java.util.Stack;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
/** /**
* This logger simply prints what each thread is doing * This logger simply prints what each thread is doing
* to the console in a machine parsable way. * to the console in a machine parsable way.
* *
* Created by covers1624 on 11/02/19. * <p>Created by covers1624 on 11/02/19.
*/ */
public class ThreadIDFFLogger extends IFernflowerLogger { public class ThreadIDFFLogger extends IFernflowerLogger {
public final PrintStream stdOut;
public final PrintStream stdErr;
public final PrintStream stdOut; private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new);
public final PrintStream stdErr; private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new);
private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); public ThreadIDFFLogger() {
private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); this(System.err, System.out);
}
public ThreadIDFFLogger() { public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) {
this(System.err, System.out); this.stdOut = stdOut;
} this.stdErr = stdErr;
}
public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { @Override
this.stdOut = stdOut; public void writeMessage(String message, Severity severity) {
this.stdErr = stdErr; System.err.println(message);
} }
@Override @Override
public void writeMessage(String message, Severity severity) { public void writeMessage(String message, Severity severity, Throwable t) {
System.err.println(message); System.err.println(message);
} t.printStackTrace(System.err);
}
@Override private void print() {
public void writeMessage(String message, Severity severity, Throwable t) { Thread thread = Thread.currentThread();
System.err.println(message); long id = thread.getId();
t.printStackTrace(System.err);
}
private void print() { if (line.get().isEmpty()) {
Thread thread = Thread.currentThread(); System.out.println(MessageFormat.format("{0} :: waiting", id));
long id = thread.getId(); return;
if (line.get().isEmpty()) { }
System.out.println(MessageFormat.format("{0} :: waiting", id));
return;
}
String line = this.line.get().peek();
System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim());
}
@Override String line = this.line.get().peek();
public void startReadingClass(String className) { System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim());
workingClass.get().push(className); }
line.get().push("Decompiling " + className);
print();
}
@Override @Override
public void startClass(String className) { public void startReadingClass(String className) {
workingClass.get().push(className); workingClass.get().push(className);
line.get().push("Decompiling " + className); line.get().push("Decompiling " + className);
print(); print();
} }
@Override @Override
public void startMethod(String methodName) { public void startClass(String className) {
String className = workingClass.get().peek(); workingClass.get().push(className);
line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" "))); line.get().push("Decompiling " + className);
print(); print();
} }
@Override @Override
public void endMethod() { public void startMethod(String methodName) {
line.get().pop(); String className = workingClass.get().peek();
print(); line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" ")));
} print();
}
@Override @Override
public void endClass() { public void endMethod() {
line.get().pop(); line.get().pop();
workingClass.get().pop(); print();
print(); }
}
@Override @Override
public void startWriteClass(String className) { public void endClass() {
line.get().push("Writing " + className); line.get().pop();
print(); workingClass.get().pop();
} print();
}
@Override @Override
public void endWriteClass() { public void startWriteClass(String className) {
line.get().pop(); line.get().push("Writing " + className);
print(); print();
} }
@Override @Override
public void endReadingClass() { public void endWriteClass() {
line.get().pop(); line.get().pop();
workingClass.get().pop(); print();
print(); }
}
@Override
public void endReadingClass() {
line.get().pop();
workingClass.get().pop();
print();
}
} }

View File

@ -24,11 +24,11 @@
package net.fabricmc.loom.task.fernflower; package net.fabricmc.loom.task.fernflower;
import net.fabricmc.fernflower.api.IFabricResultSaver; import java.io.File;
import org.jetbrains.java.decompiler.main.DecompilerContext; import java.io.FileOutputStream;
import org.jetbrains.java.decompiler.main.extern.IResultSaver; import java.io.FileWriter;
import java.io.IOException;
import java.io.*; import java.io.PrintWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -42,108 +42,136 @@ import java.util.jar.Manifest;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import net.fabricmc.fernflower.api.IFabricResultSaver;
/** /**
* Created by covers1624 on 18/02/19. * Created by covers1624 on 18/02/19.
*/ */
public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver { public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver {
private final Supplier<File> output; private final Supplier<File> output;
private final Supplier<File> lineMapFile; private final Supplier<File> lineMapFile;
public Map<String, ZipOutputStream> outputStreams = new HashMap<>(); public Map<String, ZipOutputStream> outputStreams = new HashMap<>();
public Map<String, ExecutorService> saveExecutors = new HashMap<>(); public Map<String, ExecutorService> saveExecutors = new HashMap<>();
public PrintWriter lineMapWriter; public PrintWriter lineMapWriter;
public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) { public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) {
this.output = output; this.output = output;
this.lineMapFile = lineMapFile; this.lineMapFile = lineMapFile;
} }
@Override @Override
public void createArchive(String path, String archiveName, Manifest manifest) { public void createArchive(String path, String archiveName, Manifest manifest) {
String key = path + "/" + archiveName; String key = path + "/" + archiveName;
File file = output.get(); File file = output.get();
try {
FileOutputStream fos = new FileOutputStream(file);
ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest);
outputStreams.put(key, zos);
saveExecutors.put(key, Executors.newSingleThreadExecutor());
} catch (IOException e) {
throw new RuntimeException("Unable to create archive: " + file, e);
}
if (lineMapFile.get() != null) {
try {
lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get()));
} catch (IOException e) {
throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e);
}
}
}
@Override try {
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { FileOutputStream fos = new FileOutputStream(file);
this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null); ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest);
} outputStreams.put(key, zos);
saveExecutors.put(key, Executors.newSingleThreadExecutor());
} catch (IOException e) {
throw new RuntimeException("Unable to create archive: " + file, e);
}
@Override if (lineMapFile.get() != null) {
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) { try {
String key = path + "/" + archiveName; lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get()));
ExecutorService executor = saveExecutors.get(key); } catch (IOException e) {
executor.submit(() -> { throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e);
ZipOutputStream zos = outputStreams.get(key); }
try { }
zos.putNextEntry(new ZipEntry(entryName)); }
if (content != null) {
zos.write(content.getBytes(StandardCharsets.UTF_8));
}
} catch (IOException e) {
DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e);
}
if (mapping != null && lineMapWriter != null) {
int maxLine = 0;
int maxLineDest = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < mapping.length; i += 2) {
maxLine = Math.max(maxLine, mapping[i]);
maxLineDest = Math.max(maxLineDest, mapping[i + 1]);
builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n");
}
lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest);
lineMapWriter.println(builder.toString());
}
});
}
@Override @Override
public void closeArchive(String path, String archiveName) { public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) {
String key = path + "/" + archiveName; this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null);
ExecutorService executor = saveExecutors.get(key); }
Future<?> closeFuture = executor.submit(() -> {
ZipOutputStream zos = outputStreams.get(key);
try {
zos.close();
} catch (IOException e) {
throw new RuntimeException("Unable to close zip. " + key, e);
}
});
executor.shutdown();
try {
closeFuture.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
outputStreams.remove(key);
saveExecutors.remove(key);
if (lineMapWriter != null) {
lineMapWriter.flush();
lineMapWriter.close();
}
}
//@formatter:off @Override
@Override public void saveFolder(String path) { } public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) {
@Override public void copyFile(String source, String path, String entryName) { } String key = path + "/" + archiveName;
@Override public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { } ExecutorService executor = saveExecutors.get(key);
@Override public void saveDirEntry(String path, String archiveName, String entryName) { } executor.submit(() -> {
@Override public void copyEntry(String source, String path, String archiveName, String entry) { } ZipOutputStream zos = outputStreams.get(key);
//@formatter:on
try {
zos.putNextEntry(new ZipEntry(entryName));
if (content != null) {
zos.write(content.getBytes(StandardCharsets.UTF_8));
}
} catch (IOException e) {
DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e);
}
if (mapping != null && lineMapWriter != null) {
int maxLine = 0;
int maxLineDest = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < mapping.length; i += 2) {
maxLine = Math.max(maxLine, mapping[i]);
maxLineDest = Math.max(maxLineDest, mapping[i + 1]);
builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n");
}
lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest);
lineMapWriter.println(builder.toString());
}
});
}
@Override
public void closeArchive(String path, String archiveName) {
String key = path + "/" + archiveName;
ExecutorService executor = saveExecutors.get(key);
Future<?> closeFuture = executor.submit(() -> {
ZipOutputStream zos = outputStreams.get(key);
try {
zos.close();
} catch (IOException e) {
throw new RuntimeException("Unable to close zip. " + key, e);
}
});
executor.shutdown();
try {
closeFuture.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
outputStreams.remove(key);
saveExecutors.remove(key);
if (lineMapWriter != null) {
lineMapWriter.flush();
lineMapWriter.close();
}
}
@Override
public void saveFolder(String path) {
}
@Override
public void copyFile(String source, String path, String entryName) {
}
@Override
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
}
@Override
public void saveDirEntry(String path, String archiveName, String entryName) {
}
@Override
public void copyEntry(String source, String path, String archiveName, String entry) {
}
} }

View File

@ -24,15 +24,15 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import java.io.File;
import java.io.IOException;
import com.google.common.hash.HashCode; import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
import com.google.common.io.Files; import com.google.common.io.Files;
import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging; import org.gradle.api.logging.Logging;
import java.io.File;
import java.io.IOException;
public class Checksum { public class Checksum {
private static final Logger log = Logging.getLogger(Checksum.class); private static final Logger log = Logging.getLogger(Checksum.class);
@ -40,18 +40,22 @@ public class Checksum {
if (file == null) { if (file == null) {
return false; return false;
} }
try { try {
//noinspection deprecation //noinspection deprecation
HashCode hash = Files.asByteSource(file).hash(Hashing.sha1()); HashCode hash = Files.asByteSource(file).hash(Hashing.sha1());
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Byte hashBytes : hash.asBytes()) { for (Byte hashBytes : hash.asBytes()) {
builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1));
} }
log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?");
return builder.toString().equals(checksum); return builder.toString().equals(checksum);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return false; return false;
} }
} }

View File

@ -24,13 +24,11 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.util.List;
public class Constants { public class Constants {
public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker"; public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker";
public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker"; public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker";
@ -41,13 +39,9 @@ public class Constants {
public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath"; public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath";
public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped"; public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped";
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of( public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), new RemappedConfigurationEntry("modApi", "api", true, "compile"),
new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""),
new RemappedConfigurationEntry("modApi", "api", true, "compile"), new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, ""));
new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"),
new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""),
new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "")
);
public static final String INCLUDE = "include"; public static final String INCLUDE = "include";
public static final String MINECRAFT = "minecraft"; public static final String MINECRAFT = "minecraft";

View File

@ -32,33 +32,36 @@ import java.util.function.Consumer;
* Created by covers1624 on 20/12/18. * Created by covers1624 on 20/12/18.
*/ */
public class ConsumingOutputStream extends OutputStream { public class ConsumingOutputStream extends OutputStream {
private final Consumer<String> consumer;
private final Consumer<String> consumer; private StringBuilder buffer = new StringBuilder();
private StringBuilder buffer = new StringBuilder(); public ConsumingOutputStream(Consumer<String> consumer) {
this.consumer = consumer;
}
public ConsumingOutputStream(Consumer<String> consumer) { @Override
this.consumer = consumer; public void write(int b) throws IOException {
} char ch = (char) (b & 0xFF);
buffer.append(ch);
@Override if (ch == '\n' || ch == '\r') {
public void write(int b) throws IOException { flush();
char ch = (char) (b & 0xFF); }
buffer.append(ch); }
if (ch == '\n' || ch == '\r') {
flush();
}
}
@Override @Override
public void flush() throws IOException { public void flush() throws IOException {
String str = buffer.toString(); String str = buffer.toString();
if (str.endsWith("\r") || str.endsWith("\n")) {
str = str.trim(); if (str.endsWith("\r") || str.endsWith("\n")) {
if (!str.isEmpty()) { str = str.trim();
consumer.accept(str);
} if (!str.isEmpty()) {
buffer = new StringBuilder(); consumer.accept(str);
} }
}
buffer = new StringBuilder();
}
}
} }

View File

@ -24,33 +24,8 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import org.apache.commons.io.FilenameUtils;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.artifacts.SelfResolvingDependency;
import org.gradle.api.artifacts.query.ArtifactResolutionQuery;
import org.gradle.api.artifacts.result.ArtifactResult;
import org.gradle.api.artifacts.result.ComponentArtifactsResult;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier;
import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact;
import org.zeroturnaround.zip.ZipUtil;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -60,8 +35,21 @@ import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public abstract class DependencyProvider { import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.io.FilenameUtils;
import org.zeroturnaround.zip.ZipUtil;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.artifacts.SelfResolvingDependency;
import net.fabricmc.loom.LoomGradleExtension;
public abstract class DependencyProvider {
private LoomDependencyManager dependencyManager; private LoomDependencyManager dependencyManager;
public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception; public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception;
@ -73,13 +61,14 @@ public abstract class DependencyProvider {
} }
public void addDependency(Object object, Project project, String target) { public void addDependency(Object object, Project project, String target) {
if(object instanceof File){ if (object instanceof File) {
object = project.files(object); object = project.files(object);
} }
project.getDependencies().add(target, object); project.getDependencies().add(target, object);
} }
public void register(LoomDependencyManager dependencyManager){ public void register(LoomDependencyManager dependencyManager) {
this.dependencyManager = dependencyManager; this.dependencyManager = dependencyManager;
} }
@ -132,14 +121,17 @@ public abstract class DependencyProvider {
public Optional<File> resolveFile() { public Optional<File> resolveFile() {
Set<File> files = resolve(); Set<File> files = resolve();
if (files.isEmpty()) { if (files.isEmpty()) {
return Optional.empty(); return Optional.empty();
} else if (files.size() > 1) { } else if (files.size() > 1) {
StringBuilder builder = new StringBuilder(this.toString()); StringBuilder builder = new StringBuilder(this.toString());
builder.append(" resolves to more than one file:"); builder.append(" resolves to more than one file:");
for (File f : files) { for (File f : files) {
builder.append("\n\t-").append(f.getAbsolutePath()); builder.append("\n\t-").append(f.getAbsolutePath());
} }
throw new RuntimeException(builder.toString()); throw new RuntimeException(builder.toString());
} else { } else {
return files.stream().findFirst(); return files.stream().findFirst();
@ -151,11 +143,11 @@ public abstract class DependencyProvider {
return getDepString(); return getDepString();
} }
public String getDepString(){ public String getDepString() {
return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion(); return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion();
} }
public String getResolvedDepString(){ public String getResolvedDepString() {
return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion(); return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion();
} }
} }
@ -178,7 +170,6 @@ public abstract class DependencyProvider {
default: //File collection, try work out the classifiers default: //File collection, try work out the classifiers
List<File> sortedFiles = files.stream().sorted(Comparator.comparing(File::getName, Comparator.comparingInt(String::length))).collect(Collectors.toList()); List<File> sortedFiles = files.stream().sorted(Comparator.comparing(File::getName, Comparator.comparingInt(String::length))).collect(Collectors.toList());
//First element in sortedFiles is the one with the shortest name, we presume all the others are different classifier types of this //First element in sortedFiles is the one with the shortest name, we presume all the others are different classifier types of this
File shortest = sortedFiles.remove(0); File shortest = sortedFiles.remove(0);
String shortestName = FilenameUtils.removeExtension(shortest.getName()); //name.jar -> name String shortestName = FilenameUtils.removeExtension(shortest.getName()); //name.jar -> name
@ -192,8 +183,8 @@ public abstract class DependencyProvider {
//We appear to be right, therefore this is the normal dependency file we want //We appear to be right, therefore this is the normal dependency file we want
classifierToFile.put("", shortest); classifierToFile.put("", shortest);
int start = shortestName.length(); int start = shortestName.length();
for (File file : sortedFiles) { for (File file : sortedFiles) {
//Now we just have to work out what classifier type the other files are, this shouldn't even return an empty string //Now we just have to work out what classifier type the other files are, this shouldn't even return an empty string
String classifier = FilenameUtils.removeExtension(file.getName()).substring(start); String classifier = FilenameUtils.removeExtension(file.getName()).substring(start);
@ -206,16 +197,21 @@ public abstract class DependencyProvider {
} }
File root = classifierToFile.get(""); //We've built the classifierToFile map, now to try find a name and version for our dependency File root = classifierToFile.get(""); //We've built the classifierToFile map, now to try find a name and version for our dependency
if ("jar".equals(FilenameUtils.getExtension(root.getName())) && ZipUtil.containsEntry(root, "fabric.mod.json")) { if ("jar".equals(FilenameUtils.getExtension(root.getName())) && ZipUtil.containsEntry(root, "fabric.mod.json")) {
//It's a Fabric mod, see how much we can extract out //It's a Fabric mod, see how much we can extract out
JsonObject json = new Gson().fromJson(new String(ZipUtil.unpackEntry(root, "fabric.mod.json"), StandardCharsets.UTF_8), JsonObject.class); JsonObject json = new Gson().fromJson(new String(ZipUtil.unpackEntry(root, "fabric.mod.json"), StandardCharsets.UTF_8), JsonObject.class);
if (json == null || !json.has("id") || !json.has("version")) throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')');
if (json.has("name")) {//Go for the name field if it's got one if (json == null || !json.has("id") || !json.has("version")) {
throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')');
}
if (json.has("name")) { //Go for the name field if it's got one
name = json.get("name").getAsString(); name = json.get("name").getAsString();
} else { } else {
name = json.get("id").getAsString(); name = json.get("id").getAsString();
} }
version = json.get("version").getAsString(); version = json.get("version").getAsString();
} else { } else {
//Not a Fabric mod, just have to make something up //Not a Fabric mod, just have to make something up

View File

@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import java.io.File; import java.io.File;
@ -29,21 +30,18 @@ import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logger;
import com.google.common.io.Files;
public class DownloadUtil { public class DownloadUtil {
/** /**
* Download from the given {@link URL} to the given {@link File} so long as there are differences between them * Download from the given {@link URL} to the given {@link File} so long as there are differences between them.
* *
* @param from The URL of the file to be downloaded * @param from The URL of the file to be downloaded
* @param to The destination to be saved to, and compared against if it exists * @param to The destination to be saved to, and compared against if it exists
* @param logger The logger to print everything to, typically from {@link Project#getLogger()} * @param logger The logger to print everything to, typically from {@link Project#getLogger()}
*
* @throws IOException If an exception occurs during the process * @throws IOException If an exception occurs during the process
*/ */
public static void downloadIfChanged(URL from, File to, Logger logger) throws IOException { public static void downloadIfChanged(URL from, File to, Logger logger) throws IOException {
@ -51,24 +49,28 @@ public class DownloadUtil {
} }
/** /**
* Download from the given {@link URL} to the given {@link File} so long as there are differences between them * Download from the given {@link URL} to the given {@link File} so long as there are differences between them.
* *
* @param from The URL of the file to be downloaded * @param from The URL of the file to be downloaded
* @param to The destination to be saved to, and compared against if it exists * @param to The destination to be saved to, and compared against if it exists
* @param logger The logger to print information to, typically from {@link Project#getLogger()} * @param logger The logger to print information to, typically from {@link Project#getLogger()}
* @param quiet Whether to only print warnings (when <code>true</code>) or everything * @param quiet Whether to only print warnings (when <code>true</code>) or everything
*
* @throws IOException If an exception occurs during the process * @throws IOException If an exception occurs during the process
*/ */
public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException { public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException {
HttpURLConnection connection = (HttpURLConnection) from.openConnection(); HttpURLConnection connection = (HttpURLConnection) from.openConnection();
//If the output already exists we'll use it's last modified time //If the output already exists we'll use it's last modified time
if (to.exists()) connection.setIfModifiedSince(to.lastModified()); if (to.exists()) {
connection.setIfModifiedSince(to.lastModified());
}
//Try use the ETag if there's one for the file we're downloading //Try use the ETag if there's one for the file we're downloading
String etag = loadETag(to, logger); String etag = loadETag(to, logger);
if (etag != null) connection.setRequestProperty("If-None-Match", etag);
if (etag != null) {
connection.setRequestProperty("If-None-Match", etag);
}
//We want to download gzip compressed stuff //We want to download gzip compressed stuff
connection.setRequestProperty("Accept-Encoding", "gzip"); connection.setRequestProperty("Accept-Encoding", "gzip");
@ -80,21 +82,29 @@ public class DownloadUtil {
connection.connect(); connection.connect();
int code = connection.getResponseCode(); int code = connection.getResponseCode();
if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
//Didn't get what we expected //Didn't get what we expected
throw new IOException(connection.getResponseMessage()); throw new IOException(connection.getResponseMessage());
} }
long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1); long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1);
if (to.exists() && (code == HttpURLConnection.HTTP_NOT_MODIFIED || modifyTime > 0 && to.lastModified() >= modifyTime)) { if (to.exists() && (code == HttpURLConnection.HTTP_NOT_MODIFIED || modifyTime > 0 && to.lastModified() >= modifyTime)) {
if (!quiet) logger.info("'{}' Not Modified, skipping.", to); if (!quiet) {
logger.info("'{}' Not Modified, skipping.", to);
}
return; //What we've got is already fine return; //What we've got is already fine
} }
long contentLength = connection.getContentLengthLong(); long contentLength = connection.getContentLengthLong();
if (!quiet && contentLength >= 0) logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength));
try {//Try download to the output if (!quiet && contentLength >= 0) {
logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength));
}
try { //Try download to the output
FileUtils.copyInputStreamToFile(connection.getInputStream(), to); FileUtils.copyInputStreamToFile(connection.getInputStream(), to);
} catch (IOException e) { } catch (IOException e) {
to.delete(); //Probably isn't good if it fails to copy/save to.delete(); //Probably isn't good if it fails to copy/save
@ -102,23 +112,27 @@ public class DownloadUtil {
} }
//Set the modify time to match the server's (if we know it) //Set the modify time to match the server's (if we know it)
if (modifyTime > 0) to.setLastModified(modifyTime); if (modifyTime > 0) {
to.setLastModified(modifyTime);
}
//Save the ETag (if we know it) //Save the ETag (if we know it)
String eTag = connection.getHeaderField("ETag"); String eTag = connection.getHeaderField("ETag");
if (eTag != null) { if (eTag != null) {
//Log if we get a weak ETag and we're not on quiet //Log if we get a weak ETag and we're not on quiet
if (!quiet && eTag.startsWith("W/")) logger.warn("Weak ETag found."); if (!quiet && eTag.startsWith("W/")) {
logger.warn("Weak ETag found.");
}
saveETag(to, eTag, logger); saveETag(to, eTag, logger);
} }
} }
/** /**
* Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name * Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name.
* *
* @param file The file to produce the ETag for * @param file The file to produce the ETag for
*
* @return The (uncreated) ETag file for the given file * @return The (uncreated) ETag file for the given file
*/ */
private static File getETagFile(File file) { private static File getETagFile(File file) {
@ -126,16 +140,18 @@ public class DownloadUtil {
} }
/** /**
* Attempt to load an ETag for the given file, if it exists * Attempt to load an ETag for the given file, if it exists.
* *
* @param to The file to load an ETag for * @param to The file to load an ETag for
* @param logger The logger to print errors to if it goes wrong * @param logger The logger to print errors to if it goes wrong
*
* @return The ETag for the given file, or <code>null</code> if it doesn't exist * @return The ETag for the given file, or <code>null</code> if it doesn't exist
*/ */
private static String loadETag(File to, Logger logger) { private static String loadETag(File to, Logger logger) {
File eTagFile = getETagFile(to); File eTagFile = getETagFile(to);
if (!eTagFile.exists()) return null;
if (!eTagFile.exists()) {
return null;
}
try { try {
return Files.asCharSource(eTagFile, StandardCharsets.UTF_8).read(); return Files.asCharSource(eTagFile, StandardCharsets.UTF_8).read();
@ -146,7 +162,7 @@ public class DownloadUtil {
} }
/** /**
* Saves the given ETag for the given file, replacing it if it already exists * Saves the given ETag for the given file, replacing it if it already exists.
* *
* @param to The file to save the ETag for * @param to The file to save the ETag for
* @param eTag The ETag to be saved * @param eTag The ETag to be saved
@ -154,8 +170,12 @@ public class DownloadUtil {
*/ */
private static void saveETag(File to, String eTag, Logger logger) { private static void saveETag(File to, String eTag, Logger logger) {
File eTagFile = getETagFile(to); File eTagFile = getETagFile(to);
try { try {
if (!eTagFile.exists()) eTagFile.createNewFile(); if (!eTagFile.exists()) {
eTagFile.createNewFile();
}
Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag); Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag);
} catch (IOException e) { } catch (IOException e) {
logger.warn("Error saving ETag file '{}'.", eTagFile, e); logger.warn("Error saving ETag file '{}'.", eTagFile, e);
@ -163,10 +183,9 @@ public class DownloadUtil {
} }
/** /**
* Format the given number of bytes as a more human readable string * Format the given number of bytes as a more human readable string.
* *
* @param bytes The number of bytes * @param bytes The number of bytes
*
* @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate * @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate
*/ */
private static String toNiceSize(long bytes) { private static String toNiceSize(long bytes) {
@ -192,8 +211,9 @@ public class DownloadUtil {
} }
File etagFile = getETagFile(file); File etagFile = getETagFile(file);
if (etagFile.exists()) { if (etagFile.exists()) {
etagFile.delete(); etagFile.delete();
} }
} }
} }

View File

@ -24,23 +24,23 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory; import org.gradle.api.model.ObjectFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//This is used to bridge the gap over large gradle api changes. //This is used to bridge the gap over large gradle api changes.
public class GradleSupport { public class GradleSupport {
public static RegularFileProperty getfileProperty(Project project) {
public static RegularFileProperty getfileProperty(Project project){
try { try {
//First try the new method, if that fails fall back. //First try the new method, if that fails fall back.
return getfilePropertyModern(project); return getfilePropertyModern(project);
} catch (Exception e){ } catch (Exception e) {
//Nope //Nope
} }
return getfilePropertyLegacy(project); return getfilePropertyLegacy(project);
} }
@ -51,7 +51,7 @@ public class GradleSupport {
return (RegularFileProperty) method.invoke(objectFactory); return (RegularFileProperty) method.invoke(objectFactory);
} }
private static RegularFileProperty getfilePropertyLegacy(Project project){ private static RegularFileProperty getfilePropertyLegacy(Project project) {
return project.getLayout().fileProperty(); return project.getLayout().fileProperty();
} }
} }

View File

@ -24,17 +24,15 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import groovy.util.Node;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public final class GroovyXmlUtil { import groovy.util.Node;
private GroovyXmlUtil() {
} public final class GroovyXmlUtil {
private GroovyXmlUtil() { }
public static Node getOrCreateNode(Node parent, String name) { public static Node getOrCreateNode(Node parent, String name) {
for (Object object : parent.children()) { for (Object object : parent.children()) {

View File

@ -24,138 +24,160 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.loom.util.progress.ProgressLogger; import static java.text.MessageFormat.format;
import org.gradle.api.logging.Logger;
import org.objectweb.asm.*;
import java.io.*; import java.io.BufferedReader;
import java.nio.file.*; import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static java.text.MessageFormat.format; import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import net.fabricmc.loom.util.progress.ProgressLogger;
/** /**
* TODO, Move to stitch. * TODO, Move to stitch.
* Created by covers1624 on 18/02/19. * Created by covers1624 on 18/02/19.
*/ */
public class LineNumberRemapper { public class LineNumberRemapper {
private final Map<String, RClass> lineMap = new HashMap<>();
private final Map<String, RClass> lineMap = new HashMap<>(); public void readMappings(File lineMappings) {
try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) {
RClass clazz = null;
String line = null;
int i = 0;
public void readMappings(File lineMappings) { try {
try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { while ((line = reader.readLine()) != null) {
RClass clazz = null; if (line.isEmpty()) {
String line = null; continue;
int i = 0; }
try {
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
String[] segs = line.trim().split("\t");
if (line.charAt(0) != '\t') {
clazz = lineMap.computeIfAbsent(segs[0], RClass::new);
clazz.maxLine = Integer.parseInt(segs[1]);
clazz.maxLineDest = Integer.parseInt(segs[2]);
} else {
clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1]));
}
i++;
}
} catch (Exception e) {
throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e);
}
} catch (IOException e) {
throw new RuntimeException("Exception reading LineMappings file.", e);
}
}
public void process(ProgressLogger logger, Path input, Path output) throws IOException { String[] segs = line.trim().split("\t");
Files.walkFileTree(input, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String rel = input.relativize(file).toString();
Path dst = output.resolve(rel);
Path parent = dst.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
String fName = file.getFileName().toString();
if (fName.endsWith(".class")) {
if (Files.exists(dst)) {
Files.delete(dst);
}
String idx = rel.substring(0, rel.length() - 6);
if (logger != null) {
logger.progress("Remapping " + idx);
}
int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped. if (line.charAt(0) != '\t') {
if (dollarPos >= 0) { clazz = lineMap.computeIfAbsent(segs[0], RClass::new);
idx = idx.substring(0, dollarPos); clazz.maxLine = Integer.parseInt(segs[1]);
} clazz.maxLineDest = Integer.parseInt(segs[2]);
if (lineMap.containsKey(idx)) { } else {
try (InputStream is = Files.newInputStream(file)) { clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1]));
ClassReader reader = new ClassReader(is); }
ClassWriter writer = new ClassWriter(0);
reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0); i++;
Files.write(dst, writer.toByteArray()); }
} } catch (Exception e) {
} throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e);
}
} catch (IOException e) {
throw new RuntimeException("Exception reading LineMappings file.", e);
}
}
} else { public void process(ProgressLogger logger, Path input, Path output) throws IOException {
Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); Files.walkFileTree(input, new SimpleFileVisitor<Path>() {
} @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String rel = input.relativize(file).toString();
Path dst = output.resolve(rel);
Path parent = dst.getParent();
return FileVisitResult.CONTINUE; if (parent != null) {
} Files.createDirectories(parent);
}); }
}
private static class LineNumberVisitor extends ClassVisitor { String fName = file.getFileName().toString();
private final RClass rClass; if (fName.endsWith(".class")) {
if (Files.exists(dst)) {
Files.delete(dst);
}
public LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { String idx = rel.substring(0, rel.length() - 6);
super(api, classVisitor);
this.rClass = rClass;
}
@Override if (logger != null) {
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { logger.progress("Remapping " + idx);
return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { }
@Override
public void visitLineNumber(int line, Label start) {
int tLine = line;
if (tLine <= 0) {
super.visitLineNumber(line, start);
} else if (tLine >= rClass.maxLine) {
super.visitLineNumber(rClass.maxLineDest, start);
} else {
Integer matchedLine = null;
while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) {
tLine++;
}
super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start);
}
}
};
}
}
private static class RClass { int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped.
private final String name; if (dollarPos >= 0) {
private int maxLine; idx = idx.substring(0, dollarPos);
private int maxLineDest; }
private Map<Integer, Integer> lineMap = new HashMap<>();
private RClass(String name) { if (lineMap.containsKey(idx)) {
this.name = name; try (InputStream is = Files.newInputStream(file)) {
} ClassReader reader = new ClassReader(is);
} ClassWriter writer = new ClassWriter(0);
reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0);
Files.write(dst, writer.toByteArray());
}
}
} else {
Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING);
}
return FileVisitResult.CONTINUE;
}
});
}
private static class LineNumberVisitor extends ClassVisitor {
private final RClass rClass;
LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) {
super(api, classVisitor);
this.rClass = rClass;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public void visitLineNumber(int line, Label start) {
int tLine = line;
if (tLine <= 0) {
super.visitLineNumber(line, start);
} else if (tLine >= rClass.maxLine) {
super.visitLineNumber(rClass.maxLineDest, start);
} else {
Integer matchedLine = null;
while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) {
tLine++;
}
super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start);
}
}
};
}
}
private static class RClass {
private final String name;
private int maxLine;
private int maxLineDest;
private Map<Integer, Integer> lineMap = new HashMap<>();
private RClass(String name) {
this.name = name;
}
}
} }

View File

@ -24,19 +24,24 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.gson.JsonObject; import java.io.File;
import net.fabricmc.loom.LoomGradleExtension; import java.util.ArrayList;
import net.fabricmc.loom.providers.MappingsProvider; import java.util.HashMap;
import net.fabricmc.loom.util.DependencyProvider.DependencyInfo; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gson.JsonObject;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalModuleDependency; import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import java.io.File; import net.fabricmc.loom.LoomGradleExtension;
import java.util.*; import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.DependencyProvider.DependencyInfo;
public class LoomDependencyManager { public class LoomDependencyManager {
private static class ProviderList { private static class ProviderList {
@ -50,27 +55,30 @@ public class LoomDependencyManager {
private List<DependencyProvider> dependencyProviderList = new ArrayList<>(); private List<DependencyProvider> dependencyProviderList = new ArrayList<>();
public void addProvider(DependencyProvider provider){ public void addProvider(DependencyProvider provider) {
if(dependencyProviderList.contains(provider)){ if (dependencyProviderList.contains(provider)) {
throw new RuntimeException("Provider is already registered"); throw new RuntimeException("Provider is already registered");
} }
if(getProvider(provider.getClass()) != null){
if (getProvider(provider.getClass()) != null) {
throw new RuntimeException("Provider of this type is already registered"); throw new RuntimeException("Provider of this type is already registered");
} }
provider.register(this); provider.register(this);
dependencyProviderList.add(provider); dependencyProviderList.add(provider);
} }
public <T> T getProvider(Class<T> clazz){ public <T> T getProvider(Class<T> clazz) {
for(DependencyProvider provider : dependencyProviderList){ for (DependencyProvider provider : dependencyProviderList) {
if(provider.getClass() == clazz){ if (provider.getClass() == clazz) {
return (T) provider; return (T) provider;
} }
} }
return null; return null;
} }
public void handleDependencies(Project project){ public void handleDependencies(Project project) {
List<Runnable> afterTasks = new ArrayList<>(); List<Runnable> afterTasks = new ArrayList<>();
MappingsProvider mappingsProvider = null; MappingsProvider mappingsProvider = null;
@ -80,7 +88,7 @@ public class LoomDependencyManager {
Map<String, ProviderList> providerListMap = new HashMap<>(); Map<String, ProviderList> providerListMap = new HashMap<>();
List<ProviderList> targetProviders = new ArrayList<>(); List<ProviderList> targetProviders = new ArrayList<>();
for(DependencyProvider provider : dependencyProviderList){ for (DependencyProvider provider : dependencyProviderList) {
providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> { providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> {
ProviderList list = new ProviderList(k); ProviderList list = new ProviderList(k);
targetProviders.add(list); targetProviders.add(list);
@ -101,6 +109,7 @@ public class LoomDependencyManager {
configuration.getDependencies().forEach(dependency -> { configuration.getDependencies().forEach(dependency -> {
for (DependencyProvider provider : list.providers) { for (DependencyProvider provider : list.providers) {
DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration); DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration);
try { try {
provider.provide(info, project, extension, afterTasks::add); provider.provide(info, project, extension, afterTasks::add);
} catch (Exception e) { } catch (Exception e) {
@ -114,13 +123,7 @@ public class LoomDependencyManager {
String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion; String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion;
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
ModCompileRemapper.remapDependencies( ModCompileRemapper.remapDependencies(project, mappingsKey, extension, project.getConfigurations().getByName(entry.getSourceConfiguration()), project.getConfigurations().getByName(entry.getRemappedConfiguration()), project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), afterTasks::add);
project, mappingsKey, extension,
project.getConfigurations().getByName(entry.getSourceConfiguration()),
project.getConfigurations().getByName(entry.getRemappedConfiguration()),
project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())),
afterTasks::add
);
} }
} }
@ -133,9 +136,11 @@ public class LoomDependencyManager {
for (Dependency dependency : configuration.getDependencies()) { for (Dependency dependency : configuration.getDependencies()) {
DependencyInfo info = DependencyInfo.create(project, dependency, configuration); DependencyInfo info = DependencyInfo.create(project, dependency, configuration);
for (File input : info.resolve()) { for (File input : info.resolve()) {
if (seenFiles.add(input)) { if (seenFiles.add(input)) {
ModProcessor.readInstallerJson(input, project); ModProcessor.readInstallerJson(input, project);
if (extension.getInstallerJson() != null) { if (extension.getInstallerJson() != null) {
project.getLogger().info("Found installer JSON in " + info); project.getLogger().info("Found installer JSON in " + info);
break; //Found it, probably don't need to look any further break; //Found it, probably don't need to look any further
@ -156,7 +161,7 @@ public class LoomDependencyManager {
} }
} }
private static void handleInstallerJson(JsonObject jsonObject, Project project){ private static void handleInstallerJson(JsonObject jsonObject, Project project) {
JsonObject libraries = jsonObject.get("libraries").getAsJsonObject(); JsonObject libraries = jsonObject.get("libraries").getAsJsonObject();
Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES); Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES);
Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor"); Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor");
@ -171,16 +176,15 @@ public class LoomDependencyManager {
project.getLogger().debug("Loom adding " + name + " from installer JSON"); project.getLogger().debug("Loom adding " + name + " from installer JSON");
if(jsonElement.getAsJsonObject().has("url")){ if (jsonElement.getAsJsonObject().has("url")) {
String url = jsonElement.getAsJsonObject().get("url").getAsString(); String url = jsonElement.getAsJsonObject().get("url").getAsString();
long count = project.getRepositories().stream() long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
.filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
.map(artifactRepository -> (MavenArtifactRepository) artifactRepository) .map(artifactRepository -> (MavenArtifactRepository) artifactRepository)
.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count(); .filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count();
if(count == 0){
if (count == 0) {
project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString())); project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString()));
} }
} }
}); });
} }

View File

@ -24,32 +24,28 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils;
import org.gradle.api.Project;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays; import java.util.Arrays;
public class MapJarsTiny { import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class MapJarsTiny {
public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, Project project) throws IOException { public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, Project project) throws IOException {
String fromM = "official"; String fromM = "official";
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider(); MappingsProvider mappingsProvider = extension.getMappingsProvider();
Path[] classpath = mapProvider.getMapperPaths().stream() Path[] classpath = mapProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
.map(File::toPath)
.toArray(Path[]::new);
Path input = jarProvider.getMergedJar().toPath(); Path input = jarProvider.getMergedJar().toPath();
Path outputMapped = mapProvider.getMappedJar().toPath(); Path outputMapped = mapProvider.getMappedJar().toPath();
@ -60,11 +56,7 @@ public class MapJarsTiny {
project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
TinyRemapper remapper = TinyRemapper.newRemapper() TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).renameInvalidLocals(true).rebuildSourceFilenames(true).build();
.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.build();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
outputConsumer.addNonClassFiles(input); outputConsumer.addNonClassFiles(input);

View File

@ -24,15 +24,13 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftLibraryProvider;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class MinecraftVersionInfo { public class MinecraftVersionInfo {
public List<Library> libraries; public List<Library> libraries;
public Map<String, Downloads> downloads; public Map<String, Downloads> downloads;
@ -93,14 +91,16 @@ public class MinecraftVersionInfo {
return ""; return "";
} else { } else {
JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())); JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch()));
if(element == null){
if (element == null) {
return ""; return "";
} }
return "-" + element.getAsString().replace("\"", ""); return "-" + element.getAsString().replace("\"", "");
} }
} }
public boolean isNative(){ public boolean isNative() {
return getClassifier().contains("natives"); return getClassifier().contains("natives");
} }
@ -110,6 +110,7 @@ public class MinecraftVersionInfo {
} }
boolean success = false; boolean success = false;
for (Rule rule : this.rules) { for (Rule rule : this.rules) {
if (rule.os != null && rule.os.name != null) { if (rule.os != null && rule.os.name != null) {
if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) {
@ -119,6 +120,7 @@ public class MinecraftVersionInfo {
success = rule.action.equalsIgnoreCase("allow"); success = rule.action.equalsIgnoreCase("allow");
} }
} }
return success; return success;
} }
@ -126,9 +128,11 @@ public class MinecraftVersionInfo {
if (artifact == null) { if (artifact == null) {
artifact = new Artifact(name); artifact = new Artifact(name);
} }
if(natives != null){
if (natives != null) {
JsonElement jsonElement = natives.get(OperatingSystem.getOS()); JsonElement jsonElement = natives.get(OperatingSystem.getOS());
if(jsonElement != null){
if (jsonElement != null) {
return artifact.getArtifact(jsonElement.getAsString()); return artifact.getArtifact(jsonElement.getAsString());
} }
} }
@ -139,15 +143,17 @@ public class MinecraftVersionInfo {
private class Artifact { private class Artifact {
private final String domain, name, version, classifier, ext; private final String domain, name, version, classifier, ext;
public Artifact(String name) { Artifact(String name) {
String[] splitedArtifact = name.split(":"); String[] splitedArtifact = name.split(":");
int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@');
if (idx != -1) { if (idx != -1) {
ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1);
splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx);
} else { } else {
ext = "jar"; ext = "jar";
} }
this.domain = splitedArtifact[0]; this.domain = splitedArtifact[0];
this.name = splitedArtifact[1]; this.name = splitedArtifact[1];
this.version = splitedArtifact[2]; this.version = splitedArtifact[2];
@ -156,15 +162,19 @@ public class MinecraftVersionInfo {
public String getArtifact(String classifier) { public String getArtifact(String classifier) {
String ret = domain + ":" + name + ":" + version; String ret = domain + ":" + name + ":" + version;
if (classifier != null && classifier.indexOf('$') > -1) { if (classifier != null && classifier.indexOf('$') > -1) {
classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH);
} }
if (classifier != null) { if (classifier != null) {
ret += ":" + classifier; ret += ":" + classifier;
} }
if (!"jar".equals(ext)) { if (!"jar".equals(ext)) {
ret += "@" + ext; ret += "@" + ext;
} }
return ret; return ret;
} }

View File

@ -24,15 +24,6 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import net.fabricmc.tinyremapper.TinyRemapper;
import org.objectweb.asm.commons.Remapper;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -41,86 +32,91 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.zip.ZipEntry; 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 { public final class MixinRefmapHelper {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private MixinRefmapHelper() { private MixinRefmapHelper() { }
} public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) {
File output = outputPath.toFile();
Set<String> mixinFilenames = findMixins(output, true);
public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) { if (mixinFilenames.size() > 0) {
File output = outputPath.toFile(); return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
Set<String> mixinFilenames = findMixins(output, true); @Override
protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class);
if (mixinFilenames.size() > 0) { if (!json.has("refmap")) {
return ZipUtil.transformEntries( json.addProperty("refmap", filename);
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);
if (!json.has("refmap")) {
json.addProperty("refmap", filename);
}
if (!json.has("minVersion") && mixinVersion != null) {
json.addProperty("minVersion", mixinVersion);
}
return GSON.toJson(json);
}
})).toArray(ZipEntryTransformerEntry[]::new)
);
} else {
return false;
}
}
private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { if (!json.has("minVersion") && mixinVersion != null) {
// first, identify all of the mixin files json.addProperty("minVersion", mixinVersion);
Set<String> mixinFilename = new HashSet<>(); }
// TODO: this is a lovely hack
ZipUtil.iterate(output, (stream, entry) -> {
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);
if (json != null) { return GSON.toJson(json);
boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); }
boolean hasClient = json.has("client") && json.get("client").isJsonArray(); })).toArray(ZipEntryTransformerEntry[]::new));
boolean hasServer = json.has("server") && json.get("server").isJsonArray(); } else {
return false;
}
}
if (json.has("package") && (hasMixins || hasClient || hasServer)) { private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) {
if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { // first, identify all of the mixin files
mixinFilename.add(entry.getName()); Set<String> mixinFilename = new HashSet<>();
} // TODO: this is a lovely hack
} ZipUtil.iterate(output, (stream, entry) -> {
} if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) {
} catch (Exception e) { // JSON file in root directory
// ... try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) {
} JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class);
}
});
return mixinFilename;
}
private static Set<String> findRefmaps(File output) { if (json != null) {
// first, identify all of the mixin refmaps boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray();
Set<String> mixinRefmapFilenames = new HashSet<>(); boolean hasClient = json.has("client") && json.get("client").isJsonArray();
// TODO: this is also a lovely hack boolean hasServer = json.has("server") && json.get("server").isJsonArray();
ZipUtil.iterate(output, (stream, entry) -> {
if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { if (json.has("package") && (hasMixins || hasClient || hasServer)) {
// JSON file in root directory if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) {
try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { mixinFilename.add(entry.getName());
JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); }
if (json != null && json.has("refmap")) { }
mixinRefmapFilenames.add(json.get("refmap").getAsString()); }
} } catch (Exception e) {
} catch (Exception e) { // ...
// ... }
} }
} });
}); return mixinFilename;
return mixinRefmapFilenames; }
}
private static Set<String> findRefmaps(File output) {
// first, identify all of the mixin refmaps
Set<String> mixinRefmapFilenames = new HashSet<>();
// TODO: this is also a lovely hack
ZipUtil.iterate(output, (stream, entry) -> {
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);
if (json != null && json.has("refmap")) {
mixinRefmapFilenames.add(json.get("refmap").getAsString());
}
} catch (Exception e) {
// ...
}
}
});
return mixinRefmapFilenames;
}
} }

View File

@ -24,7 +24,11 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.loom.LoomGradleExtension; import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.Dependency;
@ -40,10 +44,7 @@ import org.gradle.api.logging.Logger;
import org.gradle.jvm.JvmLibrary; import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact; import org.gradle.language.base.artifact.SourcesArtifact;
import java.io.File; import net.fabricmc.loom.LoomGradleExtension;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
public class ModCompileRemapper { public class ModCompileRemapper {
public static void remapDependencies(Project project, String mappingsPrefix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) { public static void remapDependencies(Project project, String mappingsPrefix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) {
@ -93,7 +94,7 @@ public class ModCompileRemapper {
} }
/** /**
* Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json * Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json.
*/ */
private static boolean isFabricMod(Project project, Logger logger, ResolvedArtifact artifact, String notation) { private static boolean isFabricMod(Project project, Logger logger, ResolvedArtifact artifact, String notation) {
File input = artifact.getFile(); File input = artifact.getFile();
@ -112,15 +113,18 @@ public class ModCompileRemapper {
project.getLogger().info(":providing " + notation); project.getLogger().info(":providing " + notation);
DependencyHandler dependencies = project.getDependencies(); DependencyHandler dependencies = project.getDependencies();
Dependency dep = dependencies.module(notation); Dependency dep = dependencies.module(notation);
if (dep instanceof ModuleDependency) { if (dep instanceof ModuleDependency) {
((ModuleDependency) dep).setTransitive(false); ((ModuleDependency) dep).setTransitive(false);
} }
dependencies.add(regularCompile.getName(), dep); dependencies.add(regularCompile.getName(), dep);
} }
private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) { private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) {
File input = artifact.getFile(); File input = artifact.getFile();
File output = new File(modStore, remappedFilename + ".jar"); File output = new File(modStore, remappedFilename + ".jar");
if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) { if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) {
//If the output doesn't exist, or appears to be outdated compared to the input we'll remap it //If the output doesn't exist, or appears to be outdated compared to the input we'll remap it
try { try {
@ -129,7 +133,7 @@ public class ModCompileRemapper {
throw new RuntimeException("Failed to remap mod", e); throw new RuntimeException("Failed to remap mod", e);
} }
if (!output.exists()){ if (!output.exists()) {
throw new RuntimeException("Failed to remap mod"); throw new RuntimeException("Failed to remap mod");
} }
@ -142,10 +146,10 @@ public class ModCompileRemapper {
} }
private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) { private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) {
@SuppressWarnings ("unchecked") @SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
.forComponents(artifact.getId().getComponentIdentifier())// .forComponents(artifact.getId().getComponentIdentifier())//
.withArtifacts(JvmLibrary.class, SourcesArtifact.class); .withArtifacts(JvmLibrary.class, SourcesArtifact.class);
for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) {
for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) {
if (srcArtifact instanceof ResolvedArtifactResult) { if (srcArtifact instanceof ResolvedArtifactResult) {
@ -153,6 +157,7 @@ public class ModCompileRemapper {
} }
} }
} }
return null; return null;
} }

View File

@ -24,23 +24,6 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.internal.impldep.aQute.lib.strings.Strings;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.commons.FileUtils;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -54,18 +37,39 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.apache.commons.io.IOUtils;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.commons.FileUtils;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.internal.impldep.aQute.lib.strings.Strings;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.providers.MinecraftMappedProvider;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class ModProcessor { public class ModProcessor {
private static final Gson GSON = new Gson(); private static final Gson GSON = new Gson();
public static void processMod(File input, File output, Project project, Configuration config) throws IOException { public static void processMod(File input, File output, Project project, Configuration config) throws IOException {
if(output.exists()){ if (output.exists()) {
output.delete(); output.delete();
} }
remapJar(input, output, project); remapJar(input, output, project);
//Enable this if you want your nested jars to be extracted, this will extract **all** jars //Enable this if you want your nested jars to be extracted, this will extract **all** jars
if(project.getExtensions().getByType(LoomGradleExtension.class).extractJars){ if (project.getExtensions().getByType(LoomGradleExtension.class).extractJars) {
handleNestedJars(input, project, config); handleNestedJars(input, project, config);
} }
//Always strip the nested jars //Always strip the nested jars
stripNestedJars(output); stripNestedJars(output);
} }
@ -77,15 +81,20 @@ public class ModProcessor {
private static void handleNestedJars(File input, Project project, Configuration config) throws IOException { private static void handleNestedJars(File input, Project project, Configuration config) throws IOException {
JarFile jarFile = new JarFile(input); JarFile jarFile = new JarFile(input);
JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json"); JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json");
if(modJsonEntry == null){
if (modJsonEntry == null) {
return; return;
} }
try(InputStream inputStream = jarFile.getInputStream(modJsonEntry)){
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class); JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
if(json == null || !json.has("jars")){
if (json == null || !json.has("jars")) {
return; return;
} }
JsonArray jsonArray = json.getAsJsonArray("jars"); JsonArray jsonArray = json.getAsJsonArray("jars");
for (int i = 0; i < jsonArray.size(); i++) { for (int i = 0; i < jsonArray.size(); i++) {
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
String fileName = jsonObject.get("file").getAsString(); String fileName = jsonObject.get("file").getAsString();
@ -99,19 +108,22 @@ public class ModProcessor {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
JarEntry entry = parentJar.getJarEntry(fileName); JarEntry entry = parentJar.getJarEntry(fileName);
if(entry == null){
if (entry == null) {
throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName())); throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName()));
} }
File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/"))); File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/")));
try(InputStream jarStream = parentJar.getInputStream(entry)) {
try (InputStream jarStream = parentJar.getInputStream(entry)) {
FileUtils.copy(jarStream, nestedFile); FileUtils.copy(jarStream, nestedFile);
} }
File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/"))); File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/")));
processMod(nestedFile, remappedFile, project, config); processMod(nestedFile, remappedFile, project, config);
if(!remappedFile.exists()){ if (!remappedFile.exists()) {
throw new RuntimeException("Failed to find processed nested jar"); throw new RuntimeException("Failed to find processed nested jar");
} }
@ -119,7 +131,7 @@ public class ModProcessor {
project.getDependencies().add(config.getName(), project.files(remappedFile)); project.getDependencies().add(config.getName(), project.files(remappedFile));
} }
private static void stripNestedJars(File file){ private static void stripNestedJars(File file) {
//Strip out all contained jar info as we dont want loader to try and load the jars contained in dev. //Strip out all contained jar info as we dont want loader to try and load the jars contained in dev.
ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
@Override @Override
@ -143,29 +155,22 @@ public class ModProcessor {
Path mappings = mappingsFile.toPath(); Path mappings = mappingsFile.toPath();
Path inputPath = input.getAbsoluteFile().toPath(); Path inputPath = input.getAbsoluteFile().toPath();
Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath(); Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath();
Path[] mcDeps = mappedProvider.getMapperPaths().stream() Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
.map(File::toPath)
.toArray(Path[]::new);
Set<Path> modCompiles = new HashSet<>(); Set<Path> modCompiles = new HashSet<>();
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream()
.filter((f) -> !f.equals(input))
.map(p -> {
if (p.equals(input)) {
return inputPath;
} else {
return p.toPath();
}
})
.forEach(modCompiles::add);
}
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream().filter((f) -> !f.equals(input)).map(p -> {
if (p.equals(input)) {
return inputPath;
} else {
return p.toPath();
}
}).forEach(modCompiles::add);
}
project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")"); project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")");
TinyRemapper remapper = TinyRemapper.newRemapper() TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).build();
.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM))
.build();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) { try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) {
outputConsumer.addNonClassFiles(inputPath); outputConsumer.addNonClassFiles(inputPath);
@ -178,12 +183,12 @@ public class ModProcessor {
remapper.finish(); remapper.finish();
} }
if(!output.exists()){ if (!output.exists()) {
throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath()); throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath());
} }
} }
static void readInstallerJson(File file, Project project){ static void readInstallerJson(File file, Project project) {
try { try {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
String launchMethod = extension.getLoaderLaunchMethod(); String launchMethod = extension.getLoaderLaunchMethod();
@ -193,8 +198,10 @@ public class ModProcessor {
try (JarFile jarFile = new JarFile(file)) { try (JarFile jarFile = new JarFile(file)) {
ZipEntry entry = null; ZipEntry entry = null;
if (!launchMethod.isEmpty()) { if (!launchMethod.isEmpty()) {
entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json"); entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json");
if (entry == null) { if (entry == null) {
project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back"); project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back");
} }
@ -203,6 +210,7 @@ public class ModProcessor {
if (entry == null) { if (entry == null) {
entry = jarFile.getEntry("fabric-installer.json"); entry = jarFile.getEntry("fabric-installer.json");
priority++; priority++;
if (entry == null) { if (entry == null) {
return; return;
} }

View File

@ -24,28 +24,6 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.task.RemapJarTask;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency;
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 java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
@ -56,8 +34,28 @@ import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
public class NestedJars { 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.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.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.task.RemapJarTask;
public class NestedJars {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static boolean addNestedJars(Project project, Path modJarPath) { public static boolean addNestedJars(Project project, Path modJarPath) {
@ -74,6 +72,7 @@ public class NestedJars {
protected String transform(ZipEntry zipEntry, String input) throws IOException { protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class); JsonObject json = GSON.fromJson(input, JsonObject.class);
JsonArray nestedJars = json.getAsJsonArray("jars"); JsonArray nestedJars = json.getAsJsonArray("jars");
if (nestedJars == null || !json.has("jars")) { if (nestedJars == null || !json.has("jars")) {
nestedJars = new JsonArray(); nestedJars = new JsonArray();
} }
@ -96,6 +95,7 @@ public class NestedJars {
Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE);
DependencySet dependencies = configuration.getDependencies(); DependencySet dependencies = configuration.getDependencies();
for (Dependency dependency : dependencies) { for (Dependency dependency : dependencies) {
if (dependency instanceof ProjectDependency) { if (dependency instanceof ProjectDependency) {
ProjectDependency projectDependency = (ProjectDependency) dependency; ProjectDependency projectDependency = (ProjectDependency) dependency;
@ -116,27 +116,32 @@ public class NestedJars {
fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project)); fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project));
} }
} }
for (File file : fileList) { for (File file : fileList) {
if (!file.exists()) { if (!file.exists()) {
throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath());
} }
if (file.isDirectory() || !file.getName().endsWith(".jar")) { if (file.isDirectory() || !file.getName().endsWith(".jar")) {
throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath());
} }
} }
return fileList; return fileList;
} }
//Looks for any deps that require a sub project to be built first //Looks for any deps that require a sub project to be built first
public static List<RemapJarTask> getRequiredTasks(Project project){ public static List<RemapJarTask> getRequiredTasks(Project project) {
List<RemapJarTask> remapTasks = new ArrayList<>(); List<RemapJarTask> remapTasks = new ArrayList<>();
Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE);
DependencySet dependencies = configuration.getDependencies(); DependencySet dependencies = configuration.getDependencies();
for (Dependency dependency : dependencies) { for (Dependency dependency : dependencies) {
if (dependency instanceof ProjectDependency) { if (dependency instanceof ProjectDependency) {
ProjectDependency projectDependency = (ProjectDependency) dependency; ProjectDependency projectDependency = (ProjectDependency) dependency;
Project dependencyProject = projectDependency.getDependencyProject(); Project dependencyProject = projectDependency.getDependencyProject();
for (Task task : dependencyProject.getTasksByName("remapJar", false)) { for (Task task : dependencyProject.getTasksByName("remapJar", false)) {
if (task instanceof RemapJarTask) { if (task instanceof RemapJarTask) {
remapTasks.add((RemapJarTask) task); remapTasks.add((RemapJarTask) task);
@ -144,29 +149,36 @@ public class NestedJars {
} }
} }
} }
return remapTasks; return remapTasks;
} }
//This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library //This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library
private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project){ private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project) {
List<File> fileList = new ArrayList<>(); List<File> fileList = new ArrayList<>();
for(File file : files){
for (File file : files) {
//A lib that doesnt have a mod.json, we turn it into a fake mod //A lib that doesnt have a mod.json, we turn it into a fake mod
if(!ZipUtil.containsEntry(file, "fabric.mod.json")){ if (!ZipUtil.containsEntry(file, "fabric.mod.json")) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
File tempDir = new File(extension.getUserCache(), "temp/modprocessing"); File tempDir = new File(extension.getUserCache(), "temp/modprocessing");
if(!tempDir.exists()){
if (!tempDir.exists()) {
tempDir.mkdirs(); tempDir.mkdirs();
} }
File tempFile = new File(tempDir, file.getName()); File tempFile = new File(tempDir, file.getName());
if(tempFile.exists()){
if (tempFile.exists()) {
tempFile.delete(); tempFile.delete();
} }
try { try {
FileUtils.copyFile(file, tempFile); FileUtils.copyFile(file, tempFile);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Failed to copy file", e); throw new RuntimeException("Failed to copy file", e);
} }
ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes()); ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes());
fileList.add(tempFile); fileList.add(tempFile);
} else { } else {
@ -174,11 +186,12 @@ public class NestedJars {
fileList.add(file); fileList.add(file);
} }
} }
return fileList; return fileList;
} }
//Generates a barebones mod for a dependency //Generates a barebones mod for a dependency
private static String getMod(Dependency dependency){ private static String getMod(Dependency dependency) {
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("schemaVersion", 1); jsonObject.addProperty("schemaVersion", 1);
jsonObject.addProperty("id", (dependency.getGroup().replaceAll("\\.", "_") + "_" + dependency.getName()).toLowerCase(Locale.ENGLISH)); jsonObject.addProperty("id", (dependency.getGroup().replaceAll("\\.", "_") + "_" + dependency.getName()).toLowerCase(Locale.ENGLISH));

View File

@ -27,6 +27,7 @@ package net.fabricmc.loom.util;
public class OperatingSystem { public class OperatingSystem {
public static String getOS() { public static String getOS() {
String osName = System.getProperty("os.name").toLowerCase(); String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) { if (osName.contains("win")) {
return "windows"; return "windows";
} else if (osName.contains("mac")) { } else if (osName.contains("mac")) {

View File

@ -27,43 +27,43 @@ package net.fabricmc.loom.util;
import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.ConfigurationContainer;
public class RemappedConfigurationEntry { public class RemappedConfigurationEntry {
private final String sourceConfiguration; private final String sourceConfiguration;
private final String targetConfiguration; private final String targetConfiguration;
private final String mavenScope; private final String mavenScope;
private final boolean isOnModCompileClasspath; private final boolean isOnModCompileClasspath;
public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) {
this.sourceConfiguration = sourceConfiguration; this.sourceConfiguration = sourceConfiguration;
this.targetConfiguration = targetConfiguration; this.targetConfiguration = targetConfiguration;
this.isOnModCompileClasspath = isOnModCompileClasspath; this.isOnModCompileClasspath = isOnModCompileClasspath;
this.mavenScope = mavenScope; this.mavenScope = mavenScope;
} }
public String getMavenScope() { public String getMavenScope() {
return mavenScope; return mavenScope;
} }
public boolean hasMavenScope() { public boolean hasMavenScope() {
return mavenScope != null && !mavenScope.isEmpty(); return mavenScope != null && !mavenScope.isEmpty();
} }
public boolean isOnModCompileClasspath() { public boolean isOnModCompileClasspath() {
return isOnModCompileClasspath; return isOnModCompileClasspath;
} }
public String getSourceConfiguration() { public String getSourceConfiguration() {
return sourceConfiguration; return sourceConfiguration;
} }
public String getRemappedConfiguration() { public String getRemappedConfiguration() {
return sourceConfiguration + "Mapped"; return sourceConfiguration + "Mapped";
} }
public String getTargetConfiguration(ConfigurationContainer container) { public String getTargetConfiguration(ConfigurationContainer container) {
if (container.findByName(targetConfiguration) == null) { if (container.findByName(targetConfiguration) == null) {
return "compile"; return "compile";
} }
return targetConfiguration; return targetConfiguration;
} }
} }

View File

@ -24,21 +24,6 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
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 net.fabricmc.loom.providers.MinecraftProvider;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -47,6 +32,23 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
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 org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftProvider;
public class RunConfig { public class RunConfig {
public String configName; public String configName;
public String projectName; public String projectName;
@ -70,19 +72,23 @@ public class RunConfig {
if (!Strings.isNullOrEmpty(programArgs)) { if (!Strings.isNullOrEmpty(programArgs)) {
this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs));
} }
return root; return root;
} }
public Element addXml(Node parent, String name, Map<String, String> values) { public Element addXml(Node parent, String name, Map<String, String> values) {
Document doc = parent.getOwnerDocument(); Document doc = parent.getOwnerDocument();
if (doc == null) { if (doc == null) {
doc = (Document) parent; doc = (Document) parent;
} }
Element e = doc.createElement(name); Element e = doc.createElement(name);
for (Map.Entry<String, String> entry : values.entrySet()) { for (Map.Entry<String, String> entry : values.entrySet()) {
e.setAttribute(entry.getKey(), entry.getValue()); e.setAttribute(entry.getKey(), entry.getValue());
} }
parent.appendChild(e); parent.appendChild(e);
return e; return e;
} }
@ -90,29 +96,32 @@ public class RunConfig {
private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) {
runConfig.projectName = project.getName(); runConfig.projectName = project.getName();
runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir; runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir;
runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath() + "\""; runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath() + "\"";
switch (extension.getLoaderLaunchMethod()) { switch (extension.getLoaderLaunchMethod()) {
case "launchwrapper": case "launchwrapper":
runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; runConfig.mainClass = "net.minecraft.launchwrapper.Launch";
runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER); runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER);
break; break;
default: default:
runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT); runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT);
runConfig.programArgs = ""; runConfig.programArgs = "";
break; break;
} }
// if installer.json found... // if installer.json found...
JsonObject installerJson = extension.getInstallerJson(); JsonObject installerJson = extension.getInstallerJson();
if (installerJson != null) { if (installerJson != null) {
List<String> sideKeys = ImmutableList.of(mode, "common"); List<String> sideKeys = ImmutableList.of(mode, "common");
// copy main class // copy main class
if (installerJson.has("mainClass")) { if (installerJson.has("mainClass")) {
JsonElement mainClassJson = installerJson.get("mainClass"); JsonElement mainClassJson = installerJson.get("mainClass");
if (mainClassJson.isJsonObject()) { if (mainClassJson.isJsonObject()) {
JsonObject mainClassesJson = mainClassJson.getAsJsonObject(); JsonObject mainClassesJson = mainClassJson.getAsJsonObject();
for (String s : sideKeys) { for (String s : sideKeys) {
if (mainClassesJson.has(s)) { if (mainClassesJson.has(s)) {
runConfig.mainClass = mainClassesJson.get(s).getAsString(); runConfig.mainClass = mainClassesJson.get(s).getAsString();
@ -127,9 +136,11 @@ public class RunConfig {
// copy launchwrapper tweakers // copy launchwrapper tweakers
if (installerJson.has("launchwrapper")) { if (installerJson.has("launchwrapper")) {
JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper"); JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper");
if (launchwrapperJson.has("tweakers")) { if (launchwrapperJson.has("tweakers")) {
JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers"); JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers");
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (String s : sideKeys) { for (String s : sideKeys) {
if (tweakersJson.has(s)) { if (tweakersJson.has(s)) {
for (JsonElement element : tweakersJson.getAsJsonArray(s)) { for (JsonElement element : tweakersJson.getAsJsonArray(s)) {
@ -137,15 +148,16 @@ public class RunConfig {
} }
} }
} }
runConfig.programArgs += builder.toString(); runConfig.programArgs += builder.toString();
} }
} }
} }
} }
public static RunConfig clientRunConfig(Project project){ public static RunConfig clientRunConfig(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MinecraftProvider minecraftProvider = extension.getMinecraftProvider(); MinecraftProvider minecraftProvider = extension.getMinecraftProvider();
MinecraftVersionInfo minecraftVersionInfo = minecraftProvider.versionInfo; MinecraftVersionInfo minecraftVersionInfo = minecraftProvider.versionInfo;
RunConfig ideaClient = new RunConfig(); RunConfig ideaClient = new RunConfig();
@ -157,7 +169,7 @@ public class RunConfig {
return ideaClient; return ideaClient;
} }
public static RunConfig serverRunConfig(Project project){ public static RunConfig serverRunConfig(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
RunConfig ideaServer = new RunConfig(); RunConfig ideaServer = new RunConfig();
@ -169,6 +181,7 @@ public class RunConfig {
public String fromDummy(String dummy) throws IOException { public String fromDummy(String dummy) throws IOException {
String dummyConfig; String dummyConfig;
try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) { try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) {
dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8); dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8);
} }
@ -182,10 +195,11 @@ public class RunConfig {
return dummyConfig; return dummyConfig;
} }
public static String getOSClientJVMArgs(){ public static String getOSClientJVMArgs() {
if(OperatingSystem.getOS().equalsIgnoreCase("osx")){ if (OperatingSystem.getOS().equalsIgnoreCase("osx")) {
return " -XstartOnFirstThread"; return " -XstartOnFirstThread";
} }
return ""; return "";
} }
} }

View File

@ -24,25 +24,27 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class SetupIntelijRunConfigs { 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;
public class SetupIntelijRunConfigs {
public static void setup(Project project) { public static void setup(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
File projectDir = project.file(".idea"); File projectDir = project.file(".idea");
if(!projectDir.exists()){
if (!projectDir.exists()) {
return; return;
} }
try { try {
generate(project); generate(project);
} catch (IOException e) { } catch (IOException e) {
@ -50,6 +52,7 @@ public class SetupIntelijRunConfigs {
} }
File runDir = new File(project.getRootDir(), extension.runDir); File runDir = new File(project.getRootDir(), extension.runDir);
if (!runDir.exists()) { if (!runDir.exists()) {
runDir.mkdirs(); runDir.mkdirs();
} }
@ -57,7 +60,7 @@ public class SetupIntelijRunConfigs {
private static void generate(Project project) throws IOException { private static void generate(Project project) throws IOException {
//Ensures the assets are downloaded when idea is syncing a project //Ensures the assets are downloaded when idea is syncing a project
if(Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))){ if (Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project);
MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project);
@ -68,18 +71,19 @@ public class SetupIntelijRunConfigs {
File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client.xml"); File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client.xml");
File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml"); File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml");
if(!runConfigsDir.exists()){ if (!runConfigsDir.exists()) {
runConfigsDir.mkdirs(); runConfigsDir.mkdirs();
} }
String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml");
String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml");
if(!clientRunConfigs.exists()) if (!clientRunConfigs.exists()) {
FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8);
if(!serverRunConfigs.exists()) }
if (!serverRunConfigs.exists()) {
FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8);
}
} }
} }

View File

@ -24,31 +24,26 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import com.google.common.collect.ImmutableMap; import java.io.File;
import net.fabricmc.loom.LoomGradleExtension; import java.io.IOException;
import net.fabricmc.loom.providers.MappingsProvider; import java.nio.file.Files;
import net.fabricmc.mappings.*; import java.nio.file.Path;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.stitch.util.StitchUtil;
import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.MappingsReader; import org.cadixdev.lorenz.io.MappingsReader;
import org.cadixdev.lorenz.io.TextMappingsReader;
import org.cadixdev.lorenz.model.Mapping;
import org.cadixdev.mercury.Mercury; import org.cadixdev.mercury.Mercury;
import org.cadixdev.mercury.remapper.MercuryRemapper; import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.gradle.api.Project;
import org.gradle.internal.impldep.aQute.bnd.build.Run;
import org.objectweb.asm.commons.Remapper;
import org.zeroturnaround.zip.ZipUtil; import org.zeroturnaround.zip.ZipUtil;
import org.gradle.api.Project;
import java.io.*; import net.fabricmc.loom.LoomGradleExtension;
import java.net.URI; import net.fabricmc.loom.providers.MappingsProvider;
import java.nio.file.*; import net.fabricmc.mappings.ClassEntry;
import java.nio.file.attribute.BasicFileAttributes; import net.fabricmc.mappings.EntryTriple;
import java.util.ArrayList; import net.fabricmc.mappings.FieldEntry;
import java.util.HashMap; import net.fabricmc.mappings.Mappings;
import java.util.List; import net.fabricmc.mappings.MethodEntry;
import java.util.Map; import net.fabricmc.stitch.util.StitchUtil;
public class SourceRemapper { public class SourceRemapper {
public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception { public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception {
@ -79,11 +74,13 @@ public class SourceRemapper {
for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
m.getClassPath().add(file.toPath()); m.getClassPath().add(file.toPath());
} }
if (!toNamed) { if (!toNamed) {
for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
m.getClassPath().add(file.toPath()); m.getClassPath().add(file.toPath());
} }
} }
for (Path file : extension.getUnmappedMods()) { for (Path file : extension.getUnmappedMods()) {
if (Files.isRegularFile(file)) { if (Files.isRegularFile(file)) {
m.getClassPath().add(file); m.getClassPath().add(file);
@ -104,6 +101,7 @@ public class SourceRemapper {
} }
source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar"); source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
try { try {
com.google.common.io.Files.move(destination, source); com.google.common.io.Files.move(destination, source);
} catch (IOException e) { } catch (IOException e) {
@ -113,6 +111,7 @@ public class SourceRemapper {
Path srcPath = source.toPath(); Path srcPath = source.toPath();
boolean isSrcTmp = false; boolean isSrcTmp = false;
if (!source.isDirectory()) { if (!source.isDirectory()) {
// create tmp directory // create tmp directory
isSrcTmp = true; isSrcTmp = true;
@ -144,27 +143,27 @@ public class SourceRemapper {
if (isSrcTmp) { if (isSrcTmp) {
Files.walkFileTree(srcPath, new DeletingFileVisitor()); Files.walkFileTree(srcPath, new DeletingFileVisitor());
} }
} }
private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
Files.walk(from).forEach(path -> { Files.walk(from).forEach(path -> {
Path targetPath = to.resolve(from.relativize(path).toString()); Path targetPath = to.resolve(from.relativize(path).toString());
if (!isJavaFile(path) && !Files.exists(targetPath)) {
try {
Files.copy(path, targetPath);
} catch (IOException e) {
project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e);
}
}
});
}
private static boolean isJavaFile(Path path) { if (!isJavaFile(path) && !Files.exists(targetPath)) {
String name = path.getFileName().toString(); try {
// ".java" is not a valid java file Files.copy(path, targetPath);
return name.endsWith(".java") && name.length() != 5; } catch (IOException e) {
} project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e);
}
}
});
}
private static boolean isJavaFile(Path path) {
String name = path.getFileName().toString();
// ".java" is not a valid java file
return name.endsWith(".java") && name.length() != 5;
}
public static class TinyReader extends MappingsReader { public static class TinyReader extends MappingsReader {
private final Mappings m; private final Mappings m;
@ -179,35 +178,27 @@ public class SourceRemapper {
@Override @Override
public MappingSet read(final MappingSet mappings) { public MappingSet read(final MappingSet mappings) {
for (ClassEntry entry : m.getClassEntries()) { for (ClassEntry entry : m.getClassEntries()) {
mappings.getOrCreateClassMapping(entry.get(from)) mappings.getOrCreateClassMapping(entry.get(from)).setDeobfuscatedName(entry.get(to));
.setDeobfuscatedName(entry.get(to));
} }
for (FieldEntry entry : m.getFieldEntries()) { for (FieldEntry entry : m.getFieldEntries()) {
EntryTriple fromEntry = entry.get(from); EntryTriple fromEntry = entry.get(from);
EntryTriple toEntry = entry.get(to); EntryTriple toEntry = entry.get(to);
mappings.getOrCreateClassMapping(fromEntry.getOwner()) mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
} }
for (MethodEntry entry : m.getMethodEntries()) { for (MethodEntry entry : m.getMethodEntries()) {
EntryTriple fromEntry = entry.get(from); EntryTriple fromEntry = entry.get(from);
EntryTriple toEntry = entry.get(to); EntryTriple toEntry = entry.get(to);
mappings.getOrCreateClassMapping(fromEntry.getOwner()) mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
} }
return mappings; return mappings;
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException { }
}
} }
} }

View File

@ -24,63 +24,66 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.mappings.Mappings;
import org.gradle.api.logging.Logging;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.nio.file.FileSystems;
import java.lang.ref.SoftReference; import java.nio.file.Files;
import java.nio.file.*; import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public final class StaticPathWatcher { public final class StaticPathWatcher {
public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); public static final StaticPathWatcher INSTANCE = new StaticPathWatcher();
private final Map<Path, Boolean> changeCache = new HashMap<>(); private final Map<Path, Boolean> changeCache = new HashMap<>();
private final WatchService service; private final WatchService service;
private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); private final Map<Path, WatchKey> pathsObserved = new HashMap<>();
private StaticPathWatcher() { private StaticPathWatcher() {
try { try {
service = FileSystems.getDefault().newWatchService(); service = FileSystems.getDefault().newWatchService();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public boolean hasFileChanged(Path filePath) { public boolean hasFileChanged(Path filePath) {
if(!Files.exists(filePath)){ if (!Files.exists(filePath)) {
return true; return true;
} }
WatchKey key;
while ((key = service.poll()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
Object ctx = event.context();
if (ctx instanceof Path) {
changeCache.put(((Path) ctx).toAbsolutePath(), true);
}
}
}
filePath = filePath.toAbsolutePath(); WatchKey key;
Path parentPath = filePath.getParent();
if (changeCache.containsKey(filePath)) {
return true;
} else {
if (!pathsObserved.containsKey(parentPath)) {
try {
pathsObserved.put(parentPath, parentPath.register(
service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE
));
return true; while ((key = service.poll()) != null) {
} catch (IOException e) { for (WatchEvent<?> event : key.pollEvents()) {
throw new RuntimeException(e); Object ctx = event.context();
}
} else { if (ctx instanceof Path) {
return false; changeCache.put(((Path) ctx).toAbsolutePath(), true);
} }
} }
} }
filePath = filePath.toAbsolutePath();
Path parentPath = filePath.getParent();
if (changeCache.containsKey(filePath)) {
return true;
} else {
if (!pathsObserved.containsKey(parentPath)) {
try {
pathsObserved.put(parentPath, parentPath.register(service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE));
return true;
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
return false;
}
}
}
} }

View File

@ -24,14 +24,16 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.mappings.*; import net.fabricmc.mappings.ClassEntry;
import net.fabricmc.mappings.EntryTriple;
import net.fabricmc.mappings.FieldEntry;
import net.fabricmc.mappings.Mappings;
import net.fabricmc.mappings.MethodEntry;
import net.fabricmc.tinyremapper.IMappingProvider; import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.MemberInstance; import net.fabricmc.tinyremapper.MemberInstance;
public class TinyRemapperMappingsHelper { public class TinyRemapperMappingsHelper {
private TinyRemapperMappingsHelper() { private TinyRemapperMappingsHelper() { }
}
public static IMappingProvider create(Mappings mappings, String from, String to) { public static IMappingProvider create(Mappings mappings, String from, String to) {
return (classMap, fieldMap, methodMap) -> { return (classMap, fieldMap, methodMap) -> {

View File

@ -25,7 +25,6 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
public class Version { public class Version {
private String mappingsVersion; private String mappingsVersion;
private String minecraftVersion; private String minecraftVersion;
@ -34,7 +33,7 @@ public class Version {
public Version(String version) { public Version(String version) {
this.version = version; this.version = version;
if(version.contains("+build.")){ if (version.contains("+build.")) {
this.minecraftVersion = version.substring(0, version.lastIndexOf('+')); this.minecraftVersion = version.substring(0, version.lastIndexOf('+'));
this.mappingsVersion = version.substring(version.lastIndexOf('.') + 1); this.mappingsVersion = version.substring(version.lastIndexOf('.') + 1);
} else { } else {
@ -57,4 +56,4 @@ public class Version {
public String toString() { public String toString() {
return version; return version;
} }
} }

View File

@ -54,4 +54,4 @@ public class AssetObject {
result = 31 * result + (int) (this.size ^ this.size >>> 32); result = 31 * result + (int) (this.size ^ this.size >>> 32);
return result; return result;
} }
} }

View File

@ -24,13 +24,13 @@
package net.fabricmc.loom.util.progress; package net.fabricmc.loom.util.progress;
import org.gradle.api.Project;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.gradle.api.Project;
/** /**
* Wrapper to ProgressLogger internal API * Wrapper to ProgressLogger internal API.
*/ */
public class ProgressLogger { public class ProgressLogger {
private final Object logger; private final Object logger;
@ -54,6 +54,7 @@ public class ProgressLogger {
private static Class<?> getFactoryClass() { private static Class<?> getFactoryClass() {
Class<?> progressLoggerFactoryClass = null; Class<?> progressLoggerFactoryClass = null;
try { try {
//Gradle 2.14 and higher //Gradle 2.14 and higher
progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory"); progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory");
@ -65,6 +66,7 @@ public class ProgressLogger {
// Unsupported Gradle version // Unsupported Gradle version
} }
} }
return progressLoggerFactoryClass; return progressLoggerFactoryClass;
} }
@ -73,9 +75,10 @@ public class ProgressLogger {
try { try {
return logger.getClass().getMethod(methodName, args); return logger.getClass().getMethod(methodName, args);
} catch (NoSuchMethodException ignored) { } catch (NoSuchMethodException ignored) {
//Nope
} }
} }
return null; return null;
} }
@ -85,14 +88,15 @@ public class ProgressLogger {
method.setAccessible(true); method.setAccessible(true);
return method.invoke(logger, args); return method.invoke(logger, args);
} catch (IllegalAccessException | InvocationTargetException ignored) { } catch (IllegalAccessException | InvocationTargetException ignored) {
//Nope
} }
} }
return null; return null;
} }
/** /**
* Get a Progress logger from the Gradle internal API * Get a Progress logger from the Gradle internal API.
* *
* @param project The project * @param project The project
* @param category The logger category * @param category The logger category
@ -122,9 +126,9 @@ public class ProgressLogger {
} }
/** /**
* <p>Sets the description of the operation. This should be a full, stand-alone description of the operation. * Sets the description of the operation. This should be a full, stand-alone description of the operation.
* <p> *
* <p>This must be called before {@link #started()}. * <p>This must be called before {@link #started()}
* *
* @param description The description. * @param description The description.
*/ */
@ -143,8 +147,8 @@ public class ProgressLogger {
} }
/** /**
* <p>Sets the short description of the operation. This is used in place of the full description when display space is limited. * Sets the short description of the operation. This is used in place of the full description when display space is limited.
* <p> *
* <p>This must be called before {@link #started()} * <p>This must be called before {@link #started()}
* *
* @param description The short description. * @param description The short description.
@ -155,9 +159,9 @@ public class ProgressLogger {
} }
/** /**
* <p>Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually * Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually
* also logged at the end of the operation, along with the final status message. Defaults to null. * also logged at the end of the operation, along with the final status message. Defaults to null.
* <p> *
* <p>If not specified, no logging header is logged. * <p>If not specified, no logging header is logged.
* *
* @return The logging header, possibly empty. * @return The logging header, possibly empty.
@ -167,7 +171,7 @@ public class ProgressLogger {
} }
/** /**
* <p>Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually * Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually
* also logged at the end of the operation, along with the final status message. Defaults to null. * also logged at the end of the operation, along with the final status message. Defaults to null.
* *
* @param header The header. May be empty or null. * @param header The header. May be empty or null.
@ -213,7 +217,7 @@ public class ProgressLogger {
} }
/** /**
* Logs the completion of the operation, with no final status * Logs the completion of the operation, with no final status.
*/ */
public void completed() { public void completed() {
invoke(completed); invoke(completed);