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
This commit is contained in:
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
!/README.md
!/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 'eclipse'
id 'groovy'
id 'checkstyle'
}
sourceCompatibility = 1.8
@ -60,6 +61,12 @@ dependencies {
testImplementation("org.spockframework:spock-core:1.3-groovy-2.4")
}
configurations.all {
resolutionStrategy {
force 'org.codehaus.groovy:groovy-all:2.4.12'
}
}
jar {
manifest {
attributes 'Implementation-Version': version + " Build(" + build + ")"
@ -82,6 +89,15 @@ license {
exclude '**/loom/util/DownloadUtil.java'
}
checkstyle {
configFile = file("checkstyle.xml")
toolVersion = '8.25'
}
checkstyleMain {
logging.setLevel(LogLevel.LIFECYCLE)
}
gradlePlugin {
plugins {
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;
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 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.Project;
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.idea.model.IdeaModel;
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 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.Constants;
import net.fabricmc.loom.util.GroovyXmlUtil;
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> {
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
extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration());
if (entry.isOnModCompileClasspath()) {
extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration());
extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration());
@ -137,15 +144,17 @@ public class AbstractPlugin implements Plugin<Project> {
configureScala();
Map<Project, Set<Task>> taskMap = project.getAllTasks(true);
for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) {
Project project = entry.getKey();
Set<Task> taskSet = entry.getValue();
for (Task task : taskSet) {
if (task instanceof JavaCompile
&& !(task.getName().contains("Test")) && !(task.getName().contains("test"))) {
if (task instanceof JavaCompile && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) {
JavaCompile javaCompileTask = (JavaCompile) task;
javaCompileTask.doFirst(task1 -> {
project.getLogger().lifecycle(":setting java compiler args");
try {
javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
@ -166,30 +175,31 @@ public class AbstractPlugin implements Plugin<Project> {
return project;
}
protected void configureScala() {
project.afterEvaluate(proj -> {
if (project.getPluginManager().hasPlugin("scala")) {
ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala");
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
project.getLogger().warn(":configuring scala compilation processing");
try {
task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
protected void configureScala() {
project.afterEvaluate(proj -> {
if (project.getPluginManager().hasPlugin("scala")) {
ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala");
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
project.getLogger().warn(":configuring scala compilation processing");
try {
task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath());
task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary");
} 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 name The name of the repository
* @param url The URL of the repository
* @param name The name 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
*/
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() {
// IDEA
@ -236,6 +246,7 @@ public class AbstractPlugin implements Plugin<Project> {
if (dep instanceof ResolvedDependencyResult) {
if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) {
ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId());
if (predicate.test(mci)) {
addModule(project, configuration, dep);
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() {
JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
@ -264,12 +275,18 @@ public class AbstractPlugin implements Plugin<Project> {
// Add Mixin dependencies
Project p = project;
while (true) {
boolean found = false;
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())));
}
if (found || AbstractPlugin.isRootProject(p)) break;
if (found || AbstractPlugin.isRootProject(p)) {
break;
}
p = p.getRootProject();
}
@ -330,6 +347,7 @@ public class AbstractPlugin implements Plugin<Project> {
RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar");
assert remapJarTask != null;
if (!remapJarTask.getInput().isPresent()) {
jarTask.setClassifier("dev");
remapJarTask.setClassifier("");
@ -344,8 +362,10 @@ public class AbstractPlugin implements Plugin<Project> {
project1.getTasks().getByName("build").dependsOn(remapJarTask);
Map<Project, Set<Task>> taskMap = project.getAllTasks(true);
for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) {
Set<Task> taskSet = entry.getValue();
for (Task task : taskSet) {
if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) {
//Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects
@ -384,6 +404,7 @@ public class AbstractPlugin implements Plugin<Project> {
// add modsCompile to maven-publish
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish != null) {
mavenPublish.publications((publications) -> {
for (Publication publication : publications) {
@ -393,15 +414,14 @@ public class AbstractPlugin implements Plugin<Project> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>();
GroovyXmlUtil.childrenNodesStream(dependencies)
.filter((n) -> "dependency".equals(n.name()))
.forEach((n) -> {
Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId");
if (groupId.isPresent() && artifactId.isPresent()) {
foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text());
}
});
GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> {
Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId");
Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId");
if (groupId.isPresent() && artifactId.isPresent()) {
foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text());
}
});
for (Dependency dependency : compileModsConfig.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {

View file

@ -24,28 +24,30 @@
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 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.MinecraftMappedProvider;
import net.fabricmc.loom.providers.MinecraftProvider;
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 String runDir = "run";
@ -87,77 +89,93 @@ public class LoomGradleExtension {
}
public void setInstallerJson(JsonObject object, int priority) {
if (installerJson == null || priority <= installerJsonPriority) {
this.installerJson = object;
this.installerJsonPriority = priority;
}
}
if (installerJson == null || priority <= installerJsonPriority) {
this.installerJson = object;
this.installerJsonPriority = priority;
}
}
public JsonObject getInstallerJson() {
return installerJson;
}
public JsonObject getInstallerJson() {
return installerJson;
}
public File getUserCache() {
File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom");
if (!userCache.exists()) {
userCache.mkdirs();
}
return userCache;
}
public File getRootProjectPersistentCache() {
File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getRootProjectBuildCache() {
File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getProjectBuildCache() {
File projectCache = new File(project.getBuildDir(), "loom-cache");
if(!projectCache.exists()){
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getRemappedModCache() {
File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods");
if (!remappedModCache.exists()) {
remappedModCache.mkdir();
}
return remappedModCache;
}
public File getNestedModCache() {
File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods");
if (!nestedModCache.exists()) {
nestedModCache.mkdir();
}
return nestedModCache;
}
public File getNativesJarStore(){
public File getNativesJarStore() {
File natives = new File(getUserCache(), "natives/jars");
if(!natives.exists()) {
if (!natives.exists()) {
natives.mkdirs();
}
return natives;
}
public File getNativesDirectory(){
public File getNativesDirectory() {
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion);
if(!natives.exists()) {
if (!natives.exists()) {
natives.mkdirs();
}
return natives;
}
@ -167,6 +185,7 @@ public class LoomGradleExtension {
for (Dependency dependency : config.getDependencies()) {
String group = dependency.getGroup();
String name = dependency.getName();
if (groupNameFilter.test(group, name)) {
p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion());
return dependency;
@ -181,12 +200,15 @@ public class LoomGradleExtension {
private <T> T recurseProjects(Function<Project, T> projectTFunction) {
Project p = this.project;
T result;
while (!AbstractPlugin.isRootProject(p)) {
if ((result = projectTFunction.apply(p)) != null) {
return result;
}
p = p.getRootProject();
}
result = projectTFunction.apply(p);
return result;
}
@ -197,9 +219,11 @@ public class LoomGradleExtension {
List<Configuration> configs = new ArrayList<>();
// check compile classpath first
Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath");
if (possibleCompileClasspath != null) {
configs.add(possibleCompileClasspath);
}
// failing that, buildscript
configs.addAll(p.getBuildscript().getConfigurations());
@ -242,15 +266,15 @@ public class LoomGradleExtension {
return dependencyManager;
}
public MinecraftProvider getMinecraftProvider(){
public MinecraftProvider getMinecraftProvider() {
return getDependencyManager().getProvider(MinecraftProvider.class);
}
public MinecraftMappedProvider getMinecraftMappedProvider(){
public MinecraftMappedProvider getMinecraftMappedProvider() {
return getMappingsProvider().mappedProvider;
}
public MappingsProvider getMappingsProvider(){
public MappingsProvider getMappingsProvider() {
return getDependencyManager().getProvider(MappingsProvider.class);
}
@ -259,7 +283,7 @@ public class LoomGradleExtension {
}
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");
refmapName = project.getName() + "-refmap.json";
}

View file

@ -24,26 +24,40 @@
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.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
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 {
private static File getMappedByproduct(Project project, String suffix) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider();
File mappedJar = mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {
throw new RuntimeException("Invalid mapped JAR path: " + path);
}
@ -57,7 +71,6 @@ public class LoomGradlePlugin extends AbstractPlugin {
TaskContainer tasks = target.getTasks();
tasks.register("cleanLoomBinaries", CleanLoomBinaries.class);
tasks.register("cleanLoomMappings", CleanLoomMappings.class);

View file

@ -24,41 +24,42 @@
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.InputStream;
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.Map;
import net.fabricmc.loom.util.StaticPathWatcher;
import net.fabricmc.mappings.Mappings;
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) {
mappingsPath = mappingsPath.toAbsolutePath();
if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
mappingsCache.remove(mappingsPath);
}
public Mappings get(Path mappingsPath) {
mappingsPath = mappingsPath.toAbsolutePath();
SoftReference<Mappings> ref = mappingsCache.get(mappingsPath);
if (ref != null && ref.get() != null) {
return ref.get();
} else {
try (InputStream stream = Files.newInputStream(mappingsPath)) {
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);
}
}
}
if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
mappingsCache.remove(mappingsPath);
}
SoftReference<Mappings> ref = mappingsCache.get(mappingsPath);
if (ref != null && ref.get() != null) {
return ref.get();
} else {
try (InputStream stream = Files.newInputStream(mappingsPath)) {
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;
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.util.Constants;
import net.fabricmc.loom.util.DependencyProvider;
import net.fabricmc.loom.util.Version;
import net.fabricmc.mappings.Mappings;
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 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()) {
project.getLogger().lifecycle(":extracting " + mappingsJar.getName());
try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) {
Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny");
Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath());
@ -95,11 +95,7 @@ public class MappingsProvider extends DependencyProvider {
}
project.getLogger().lifecycle(":populating field names");
new CommandProposeFieldNames().run(new String[] {
minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(),
MAPPINGS_TINY_BASE.getAbsolutePath(),
MAPPINGS_TINY.getAbsolutePath()
});
new CommandProposeFieldNames().run(new String[]{minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), MAPPINGS_TINY_BASE.getAbsolutePath(), MAPPINGS_TINY.getAbsolutePath()});
}
mappedProvider = new MinecraftMappedProvider();

View file

@ -24,7 +24,16 @@
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 org.gradle.api.GradleException;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Checksum;
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.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 static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
@ -53,13 +53,16 @@ public class MinecraftAssetsProvider {
// get existing cache files
File assets = new File(extension.getUserCache(), "assets");
if (!assets.exists()) {
assets.mkdirs();
}
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json");
if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) {
project.getLogger().lifecycle(":downloading asset index");
if (offline) {
if (assetsInfo.exists()) {
//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.start("Downloading assets...", "assets");
AssetIndex index;
try (FileReader fileReader = new FileReader(assetsInfo)) {
index = new Gson().fromJson(fileReader, AssetIndex.class);
}
Map<String, AssetObject> parent = index.getFileMap();
final int totalSize = parent.size();
int position = 0;
project.getLogger().lifecycle(":downloading assets...");
for (Map.Entry<String, AssetObject> entry : parent.entrySet()) {
AssetObject object = entry.getValue();
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);
}
}
String assetName = entry.getKey();
int end = assetName.lastIndexOf("/") + 1;
if (end > 0) {
assetName = assetName.substring(end);
}
progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded");
position++;
}

View file

@ -24,27 +24,18 @@
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.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
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 File MINECRAFT_LIBS;
private Collection<File> libs = new HashSet<>();
@ -61,6 +52,7 @@ public class MinecraftLibraryProvider {
// By default, they are all available on all sides
/* 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")) {
isClientOnly = true;
} */
@ -78,5 +70,4 @@ public class MinecraftLibraryProvider {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries");
}
}

View file

@ -24,73 +24,76 @@
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.util.Collection;
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 File MINECRAFT_MAPPED_JAR;
public File MINECRAFT_INTERMEDIARY_JAR;
public File MINECRAFT_MAPPED_JAR;
public File MINECRAFT_INTERMEDIARY_JAR;
private MinecraftProvider minecraftProvider;
private MinecraftProvider minecraftProvider;
@Override
public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception {
if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) {
throw new RuntimeException("mappings file not found");
}
@Override
public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception {
if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) {
throw new RuntimeException("mappings file not found");
}
if (!extension.getMinecraftProvider().getMergedJar().exists()) {
throw new RuntimeException("input merged jar not found");
}
if (!extension.getMinecraftProvider().getMergedJar().exists()) {
throw new RuntimeException("input merged jar not found");
}
if(!getMappedJar().exists() || !getIntermediaryJar().exists()){
if (getMappedJar().exists()) {
getMappedJar().delete();
}
if (getIntermediaryJar().exists()) {
getIntermediaryJar().delete();
}
new MapJarsTiny().mapJars(minecraftProvider, this, project);
}
if (!getMappedJar().exists() || !getIntermediaryJar().exists()) {
if (getMappedJar().exists()) {
getMappedJar().delete();
}
if (!MINECRAFT_MAPPED_JAR.exists()) {
throw new RuntimeException("mapped jar not found");
}
if (getIntermediaryJar().exists()) {
getIntermediaryJar().delete();
}
String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion;
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));
}
new MapJarsTiny().mapJars(minecraftProvider, this, project);
}
public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
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");
}
if (!MINECRAFT_MAPPED_JAR.exists()) {
throw new RuntimeException("mapped jar not found");
}
public Collection<File> getMapperPaths() {
return minecraftProvider.libraryProvider.getLibraries();
}
String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion;
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() {
return MINECRAFT_INTERMEDIARY_JAR;
}
public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
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() {
return MINECRAFT_MAPPED_JAR;
}
public Collection<File> getMapperPaths() {
return minecraftProvider.libraryProvider.getLibraries();
}
@Override
public String getTargetConfig() {
return Constants.MINECRAFT_NAMED;
}
public File getIntermediaryJar() {
return MINECRAFT_INTERMEDIARY_JAR;
}
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;
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.IOException;
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 {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo;
@ -45,6 +45,7 @@ public class MinecraftNativesProvider {
for (MinecraftVersionInfo.Library library : versionInfo.libraries) {
File libJarFile = library.getFile(jarStore);
if (library.allowed() && library.isNative() && libJarFile != null) {
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;
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.FileReader;
import java.io.IOException;
@ -44,8 +33,24 @@ import java.util.Optional;
import java.util.function.Consumer;
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 MinecraftVersionInfo versionInfo;
@ -66,25 +71,26 @@ public class MinecraftProvider extends DependencyProvider {
initFiles(project);
downloadMcJson(project, offline);
try (FileReader reader = new FileReader(MINECRAFT_JSON)) {
versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class);
}
// 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 (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) {
project.getLogger().debug("Found client and server jars, presuming up-to-date");
} else if (MINECRAFT_MERGED_JAR.exists()) {
//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");
} else {
throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists());
}
} else {
downloadJars(project.getLogger());
}
if (offline) {
if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) {
project.getLogger().debug("Found client and server jars, presuming up-to-date");
} else if (MINECRAFT_MERGED_JAR.exists()) {
//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");
} else {
throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists());
}
} else {
downloadJars(project.getLogger());
}
libraryProvider = new MinecraftLibraryProvider();
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_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
}
private void downloadMcJson(Project project, boolean offline) throws IOException {
@ -135,7 +140,7 @@ public class MinecraftProvider extends DependencyProvider {
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
if(extension.customManifest != null){
if (extension.customManifest != null) {
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
customVersion.id = minecraftVersion;
customVersion.url = extension.customManifest;
@ -143,7 +148,7 @@ public class MinecraftProvider extends DependencyProvider {
project.getLogger().lifecycle("Using custom minecraft manifest");
}
if(!optionalVersion.isPresent()){
if (!optionalVersion.isPresent()) {
optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
}
@ -165,7 +170,6 @@ public class MinecraftProvider extends DependencyProvider {
} else {
throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion);
}
}
private void downloadJars(Logger logger) throws IOException {
@ -182,6 +186,7 @@ public class MinecraftProvider extends DependencyProvider {
private void mergeJars(Logger logger) throws IOException {
logger.lifecycle(":merging jars");
try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) {
jarMerger.enableSyntheticParamsOffset();
jarMerger.merge();

View file

@ -24,29 +24,52 @@
package net.fabricmc.loom.task;
import java.io.File;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import java.io.File;
public abstract class AbstractDecompileTask extends AbstractLoomTask {
private Object input;
private Object output;
private Object lineMapFile;
private Object libraries;
private Object input;
private Object output;
private Object lineMapFile;
private Object libraries;
//@formatter:off
@InputFile
public File getInput() { 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); }
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; }
//@formatter:on
@InputFile
public File getInput() {
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);
}
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;
public abstract class AbstractLoomTask extends DefaultTask {
public AbstractLoomTask() {
setGroup("fabric");
}
}

View file

@ -24,14 +24,6 @@
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.nio.file.Files;
import java.nio.file.Path;
@ -41,99 +33,113 @@ import java.util.Collections;
import java.util.List;
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 {
private final Function<Project, RunConfig> configProvider;
private RunConfig config;
private final Function<Project, RunConfig> configProvider;
private RunConfig config;
public AbstractRunTask(Function<Project, RunConfig> config) {
super();
setGroup("fabric");
this.configProvider = config;
}
public AbstractRunTask(Function<Project, RunConfig> config) {
super();
setGroup("fabric");
this.configProvider = config;
}
@Override
public void exec() {
if (config == null) {
config = configProvider.apply(getProject());
}
@Override
public void exec() {
if (config == null) {
config = configProvider.apply(getProject());
}
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo;
MappingsProvider mappingsProvider = extension.getMappingsProvider();
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo;
MappingsProvider mappingsProvider = extension.getMappingsProvider();
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());
}
}
List<String> libs = new ArrayList<>();
classpath(libs);
List<String> argsSplit = new ArrayList<>();
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;
}
}
for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) {
libs.add(file.getAbsolutePath());
}
args(argsSplit);
setWorkingDir(new File(getProject().getRootDir(), extension.runDir));
for (Path file : extension.getUnmappedMods()) {
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
public void setWorkingDir(File dir) {
if (config == null) {
config = configProvider.apply(getProject());
}
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));
if(!dir.exists()){
dir.mkdirs();
}
super.setWorkingDir(dir);
}
for (int j = partPos + 1; j < i; j++) {
builder.append(" ").append(args[j]);
}
@Override
public String getMain() {
if (config == null) {
config = configProvider.apply(getProject());
}
builder.append(" ").append(args[i], 0, args[i].length() - 1);
argsSplit.add(builder.toString());
partPos = -1;
}
}
return config.mainClass;
}
args(argsSplit);
setWorkingDir(new File(getProject().getRootDir(), extension.runDir));
@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;
}
super.exec();
}
@Override
public void setWorkingDir(File dir) {
if (config == null) {
config = configProvider.apply(getProject());
}
if (!dir.exists()) {
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;
import net.fabricmc.loom.LoomGradleExtension;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import java.io.IOException;
import net.fabricmc.loom.LoomGradleExtension;
public class CleanLoomBinaries extends AbstractLoomTask {
@TaskAction
public void run() {
Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMinecraftProvider().getMergedJar().delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
FileUtils.deleteDirectory(extension.getNativesDirectory());
FileUtils.deleteDirectory(extension.getNativesJarStore());
} catch (IOException e) {
e.printStackTrace();
}
}
@TaskAction
public void run() {
Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMinecraftProvider().getMergedJar().delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
FileUtils.deleteDirectory(extension.getNativesDirectory());
FileUtils.deleteDirectory(extension.getNativesJarStore());
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -24,27 +24,29 @@
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.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 {
@TaskAction
public void run() {
Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMappingsProvider().MAPPINGS_TINY.delete();
extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@TaskAction
public void run() {
Project project = this.getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension.getMappingsProvider().MAPPINGS_TINY.delete();
extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete();
extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
extension.getMinecraftMappedProvider().getMappedJar().delete();
try {
Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -24,13 +24,14 @@
package net.fabricmc.loom.task;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MinecraftAssetsProvider;
import net.fabricmc.loom.providers.MinecraftNativesProvider;
import java.io.IOException;
import org.gradle.api.Project;
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 {
@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
* 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 {
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) {
ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations();
DependencyHandler handler = getProject().getDependencies();
FileCollection classpath = configurations.getByName("classpath")//
.plus(configurations.detachedConfiguration(handler.localGroovy()));
return getProject().javaexec(spec -> {
spec.classpath(classpath);
action.execute(spec);
});
}
return getProject().javaexec(spec -> {
spec.classpath(classpath);
action.execute(spec);
});
}
}

View file

@ -24,33 +24,37 @@
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.IOException;
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 {
@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
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");
String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml");
if (!clientRunConfigs.exists()) {
FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8);
}
if(!clientRunConfigs.exists())
FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8);
if(!serverRunConfigs.exists())
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);
if(!runDir.exists())
runDir.mkdirs();
}
File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir);
if (!runDir.exists()) {
runDir.mkdirs();
}
}
}

View file

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

View file

@ -24,81 +24,85 @@
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.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
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:
// 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-pack
public class GenVsCodeProjectTask extends AbstractLoomTask {
@TaskAction
public void genRuns() {
LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class);
File projectDir = getProject().file(".vscode");
@TaskAction
public void genRuns() {
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();
}
if (!projectDir.exists()) {
projectDir.mkdir();
}
VsCodeLaunch launch = new VsCodeLaunch();
launch.add(RunConfig.clientRunConfig(getProject()));
launch.add(RunConfig.serverRunConfig(getProject()));
File launchJson = new File(projectDir, "launch.json");
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(launch);
if (launchJson.exists()) {
launchJson.delete();
}
try {
FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Failed to write launch.json", e);
}
VsCodeLaunch launch = new VsCodeLaunch();
launch.add(RunConfig.clientRunConfig(getProject()));
launch.add(RunConfig.serverRunConfig(getProject()));
File runDir = new File(getProject().getRootDir(), extension.runDir);
if (!runDir.exists()) {
runDir.mkdirs();
}
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(launch);
private static class VsCodeLaunch {
public String version = "0.2.0";
public List<VsCodeConfiguration> configurations = new ArrayList<>();
try {
FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Failed to write launch.json", e);
}
public void add(RunConfig runConfig) {
configurations.add(new VsCodeConfiguration(runConfig));
}
}
File runDir = new File(getProject().getRootDir(), extension.runDir);
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;
if (!runDir.exists()) {
runDir.mkdirs();
}
}
public VsCodeConfiguration(RunConfig runConfig) {
this.name = runConfig.configName;
this.mainClass = runConfig.mainClass;
this.vmArgs = runConfig.vmArgs;
this.args = runConfig.programArgs;
}
}
private static class VsCodeLaunch {
public String version = "0.2.0";
public List<VsCodeConfiguration> configurations = new ArrayList<>();
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;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Version;
import net.fabricmc.mappings.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.MappingsReader;
import org.cadixdev.mercury.Mercury;
@ -35,149 +37,147 @@ import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Version;
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;
public class MigrateMappingsTask extends AbstractLoomTask {
@TaskAction
public void doTask() throws Throwable {
Project project = getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
Map<String, ?> properties = project.getProperties();
@TaskAction
public void doTask() throws Throwable {
Project project = getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
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")) {
mappingsFile = new File((String) properties.get("targetMappingsFile"));
} else if (properties.containsKey("targetMappingsArtifact")) {
String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":");
if (artifactName.length != 3) {
throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact"));
}
if (properties.containsKey("targetMappingsFile")) {
mappingsFile = new File((String) properties.get("targetMappingsFile"));
} else if (properties.containsKey("targetMappingsArtifact")) {
String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":");
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 minecraftVersion = v.getMinecraftVersion();
String mappingsVersion = v.getMappingsVersion();
String mappingsName = artifactName[0] + "." + artifactName[1];
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()) {
throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null"));
}
mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion);
}
if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) {
throw new RuntimeException("Must specify input and output dir!");
}
if (mappingsFile == null || !mappingsFile.exists()) {
throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null"));
}
File inputDir = new File((String) properties.get("inputDir"));
File outputDir = new File((String) properties.get("outputDir"));
if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) {
throw new RuntimeException("Must specify input and output dir!");
}
if (!inputDir.exists() || !inputDir.isDirectory()) {
throw new RuntimeException("Could not find input directory: " + inputDir);
}
File inputDir = new File((String) properties.get("inputDir"));
File outputDir = new File((String) properties.get("outputDir"));
if (!outputDir.exists()) {
if (!outputDir.mkdirs()) {
throw new RuntimeException("Could not create output directory:" + outputDir);
}
}
if (!inputDir.exists() || !inputDir.isDirectory()) {
throw new RuntimeException("Could not find input directory: " + inputDir);
}
Mappings sourceMappings = extension.getMappingsProvider().getMappings();
Mappings targetMappings;
if (!outputDir.exists()) {
if (!outputDir.mkdirs()) {
throw new RuntimeException("Could not create output directory:" + outputDir);
}
}
try (FileInputStream stream = new FileInputStream(mappingsFile)) {
targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
}
Mappings sourceMappings = extension.getMappingsProvider().getMappings();
Mappings targetMappings;
project.getLogger().lifecycle(":joining mappings");
MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read();
try (FileInputStream stream = new FileInputStream(mappingsFile)) {
targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
}
project.getLogger().lifecycle(":remapping");
Mercury mercury = new Mercury();
project.getLogger().lifecycle(":joining mappings");
MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read();
for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
mercury.getClassPath().add(file.toPath());
}
project.getLogger().lifecycle(":remapping");
Mercury mercury = new Mercury();
for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
mercury.getClassPath().add(file.toPath());
}
for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
mercury.getClassPath().add(file.toPath());
}
mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath());
mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath());
for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
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.rewrite(inputDir.toPath(), outputDir.toPath());
} catch (Exception e) {
project.getLogger().warn("Could not remap fully!", e);
}
mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
project.getLogger().lifecycle(":cleaning file descriptors");
System.gc();
}
try {
mercury.rewrite(inputDir.toPath(), outputDir.toPath());
} catch (Exception e) {
project.getLogger().warn("Could not remap fully!", e);
}
public static class MappingsJoiner extends MappingsReader {
private final Mappings sourceMappings, targetMappings;
private final String fromNamespace, toNamespace;
project.getLogger().lifecycle(":cleaning file descriptors");
System.gc();
}
public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) {
this.sourceMappings = sourceMappings;
this.targetMappings = targetMappings;
this.fromNamespace = fromNamespace;
this.toNamespace = toNamespace;
}
public static class MappingsJoiner extends MappingsReader {
private final Mappings sourceMappings, targetMappings;
private final String fromNamespace, toNamespace;
@Override
public MappingSet read(MappingSet mappings) throws IOException {
Map<String, ClassEntry> targetClasses = new HashMap<>();
Map<EntryTriple, FieldEntry> targetFields = new HashMap<>();
Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>();
public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) {
this.sourceMappings = sourceMappings;
this.targetMappings = targetMappings;
this.fromNamespace = fromNamespace;
this.toNamespace = toNamespace;
}
targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c));
targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c));
targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c));
@Override
public MappingSet read(MappingSet mappings) throws IOException {
Map<String, ClassEntry> targetClasses = new HashMap<>();
Map<EntryTriple, FieldEntry> targetFields = new HashMap<>();
Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>();
for (ClassEntry entry : sourceMappings.getClassEntries()) {
String from = entry.get(toNamespace);
String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c));
targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c));
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()) {
EntryTriple fromEntry = entry.get(toNamespace);
EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to);
}
mappings.getOrCreateClassMapping(fromEntry.getOwner())
.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
}
for (FieldEntry entry : sourceMappings.getFieldEntries()) {
EntryTriple fromEntry = entry.get(toNamespace);
EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
for (MethodEntry entry : sourceMappings.getMethodEntries()) {
EntryTriple fromEntry = entry.get(toNamespace);
EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
}
mappings.getOrCreateClassMapping(fromEntry.getOwner())
.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
}
for (MethodEntry entry : sourceMappings.getMethodEntries()) {
EntryTriple fromEntry = entry.get(toNamespace);
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
public void close() throws IOException {
return mappings;
}
}
}
@Override
public void close() throws IOException { }
}
}

View file

@ -24,6 +24,21 @@
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.providers.MappingsProvider;
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.TinyRemapper;
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 {
private RegularFileProperty input;
@ -86,6 +86,7 @@ public class RemapJarTask extends Jar {
TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM));
if (mixinMapFile.exists()) {
remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM));
}
@ -93,9 +94,11 @@ public class RemapJarTask extends Jar {
project.getLogger().lifecycle(":remapping " + input.getFileName());
StringBuilder rc = new StringBuilder("Remap classpath: ");
for (Path p : classpath) {
rc.append("\n - ").append(p.toString());
}
project.getLogger().debug(rc.toString());
TinyRemapper remapper = remapperBuilder.build();

View file

@ -24,51 +24,68 @@
package net.fabricmc.loom.task;
import net.fabricmc.loom.task.fernflower.FernFlowerTask;
import net.fabricmc.loom.util.LineNumberRemapper;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.stitch.util.StitchUtil;
import java.io.File;
import java.io.IOException;
import org.gradle.api.Project;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import java.io.File;
import java.io.IOException;
import net.fabricmc.loom.task.fernflower.FernFlowerTask;
import net.fabricmc.loom.util.LineNumberRemapper;
import net.fabricmc.loom.util.progress.ProgressLogger;
import net.fabricmc.stitch.util.StitchUtil;
public class RemapLineNumbersTask extends AbstractLoomTask {
private Object input;
private Object output;
private Object lineMapFile;
private Object input;
private Object output;
private Object lineMapFile;
@TaskAction
public void doTask() throws Throwable {
Project project = getProject();
@TaskAction
public void doTask() throws Throwable {
Project project = getProject();
project.getLogger().lifecycle(":adjusting line numbers");
LineNumberRemapper remapper = new LineNumberRemapper();
remapper.readMappings(getLineMapFile());
project.getLogger().lifecycle(":adjusting line numbers");
LineNumberRemapper remapper = new LineNumberRemapper();
remapper.readMappings(getLineMapFile());
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName());
progressLogger.start("Adjusting line numbers", "linemap");
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName());
progressLogger.start("Adjusting line numbers", "linemap");
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true);
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) {
remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/"));
} catch (IOException e) {
throw new RuntimeException(e);
}
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) {
remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/"));
} catch (IOException e) {
throw new RuntimeException(e);
}
progressLogger.completed();
}
progressLogger.completed();
}
//@formatter:off
@InputFile public File getInput() { return getProject().file(input); }
@InputFile public File getLineMapFile() { 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; }
//@formatter:on
@InputFile
public File getInput() {
return getProject().file(input);
}
@InputFile
public File getLineMapFile() {
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;
import net.fabricmc.loom.util.SourceRemapper;
import java.io.File;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import java.io.File;
import net.fabricmc.loom.util.SourceRemapper;
public class RemapSourcesJarTask extends AbstractLoomTask {
private Object input;
@ -42,13 +43,30 @@ public class RemapSourcesJarTask extends AbstractLoomTask {
SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named"));
}
//@formatter:off
@InputFile
public File getInput() { return getProject().file(input); }
@OutputFile public File getOutput() { 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; }
//@formatter:on
public File getInput() {
return getProject().file(input);
}
@OutputFile
public File getOutput() {
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;
import net.fabricmc.loom.task.AbstractDecompileTask;
import net.fabricmc.loom.task.ForkingJavaExecTask;
import net.fabricmc.loom.util.ConsumingOutputStream;
import org.gradle.api.file.FileCollection;
import static java.text.MessageFormat.format;
import java.util.ArrayList;
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.logging.LogLevel;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.logging.progress.ProgressLogger;
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.internal.service.ServiceRegistry;
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 java.util.*;
import java.util.function.Supplier;
import static java.text.MessageFormat.format;
/**
* Created by covers1624 on 9/02/19.
*/
public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask {
private boolean noFork = false;
private int numThreads = Runtime.getRuntime().availableProcessors();
private boolean noFork = false;
private int numThreads = Runtime.getRuntime().availableProcessors();
@TaskAction
public void doTask() throws Throwable {
if (!OperatingSystem.is64Bit()) {
throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements");
}
@TaskAction
public void doTask() throws Throwable {
if(!OperatingSystem.is64Bit()){
throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements");
}
Map<String, Object> options = new HashMap<>();
options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1");
options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1");
options.put(IFernflowerPreferences.LOG_LEVEL, "trace");
getLogging().captureStandardOutput(LogLevel.LIFECYCLE);
Map<String, Object> options = new HashMap<>();
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<>();
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)));
args.add(getInput().getAbsolutePath());
args.add("-o=" + getOutput().getAbsolutePath());
if (getLineMapFile() != null) {
args.add("-l=" + getLineMapFile().getAbsolutePath());
}
args.add("-t=" + getNumThreads());
if (getLineMapFile() != null) {
args.add("-l=" + getLineMapFile().getAbsolutePath());
}
//TODO, Decompiler breaks on jemalloc, J9 module-info.class?
getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath()));
args.add("-t=" + getNumThreads());
ServiceRegistry registry = ((ProjectInternal) getProject()).getServices();
ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class);
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<>();
//TODO, Decompiler breaks on jemalloc, J9 module-info.class?
getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath()));
progressGroup.started();
ExecResult result = javaexec(spec -> {
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;
}
ServiceRegistry registry = ((ProjectInternal) getProject()).getServices();
ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class);
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<>();
int sepIdx = line.indexOf("::");
String id = line.substring(0, sepIdx).trim();
String data = line.substring(sepIdx + 2).trim();
progressGroup.started();
ExecResult result = javaexec(spec -> {
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(" ");
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();
ProgressLogger logger = inUseLoggers.get(id);
result.rethrowFailure();
result.assertNormalExitValue();
}
String[] segs = data.split(" ");
//@formatter:off
@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; }
//@formatter:on
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();
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;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class FernFlowerUtils {
public static byte[] getBytecode(String externalPath, String internalPath) throws IOException {
File file = new File(externalPath);
if (internalPath == null) {
return InterpreterUtil.getBytes(file);
} else {
try (ZipFile archive = new ZipFile(file)) {
ZipEntry entry = archive.getEntry(internalPath);
if (entry == null) {
throw new IOException("Entry not found: " + internalPath);
}
return InterpreterUtil.getBytes(archive, entry);
}
}
File file = new File(externalPath);
if (internalPath == null) {
return InterpreterUtil.getBytes(file);
} else {
try (ZipFile archive = new ZipFile(file)) {
ZipEntry entry = archive.getEntry(internalPath);
if (entry == null) {
throw new IOException("Entry not found: " + internalPath);
}
return InterpreterUtil.getBytes(archive, entry);
}
}
}
}

View file

@ -24,82 +24,92 @@
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.extern.IFernflowerLogger;
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.
* Takes one parameter, a single file, each line is treated as command line input.
* Forces one input file.
* Forces one output file using '-o=/path/to/output'
*
* Created by covers1624 on 11/02/19.
*/
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 {
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;
boolean isOption = true;
for (String arg : args) {
if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') {
String value = arg.substring(5);
if ("true".equalsIgnoreCase(value)) {
value = "1";
} else if ("false".equalsIgnoreCase(value)) {
value = "0";
}
for (String arg : args) {
if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') {
String value = arg.substring(5);
options.put(arg.substring(1, 4), value);
} else {
isOption = false;
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.");
}
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);
}
}
}
if ("true".equalsIgnoreCase(value)) {
value = "1";
} else if ("false".equalsIgnoreCase(value)) {
value = "0";
}
Objects.requireNonNull(input, "Input not set.");
Objects.requireNonNull(output, "Output not set.");
options.put(arg.substring(1, 4), value);
} 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) {
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();
}
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.");
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.
*/
public class NoopFFLogger extends IFernflowerLogger {
@Override
public void writeMessage(String message, Severity severity) { }
@Override
public void writeMessage(String message, Severity severity) {
}
@Override
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;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.Stack;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
/**
* This logger simply prints what each thread is doing
* 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 final PrintStream stdOut;
public final PrintStream stdErr;
public final PrintStream stdOut;
public final PrintStream stdErr;
private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new);
private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new);
private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new);
private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new);
public ThreadIDFFLogger() {
this(System.err, System.out);
}
public ThreadIDFFLogger() {
this(System.err, System.out);
}
public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) {
this.stdOut = stdOut;
this.stdErr = stdErr;
}
public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) {
this.stdOut = stdOut;
this.stdErr = stdErr;
}
@Override
public void writeMessage(String message, Severity severity) {
System.err.println(message);
}
@Override
public void writeMessage(String message, Severity severity) {
System.err.println(message);
}
@Override
public void writeMessage(String message, Severity severity, Throwable t) {
System.err.println(message);
t.printStackTrace(System.err);
}
@Override
public void writeMessage(String message, Severity severity, Throwable t) {
System.err.println(message);
t.printStackTrace(System.err);
}
private void print() {
Thread thread = Thread.currentThread();
long id = thread.getId();
private void print() {
Thread thread = Thread.currentThread();
long id = thread.getId();
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());
}
if (line.get().isEmpty()) {
System.out.println(MessageFormat.format("{0} :: waiting", id));
return;
}
@Override
public void startReadingClass(String className) {
workingClass.get().push(className);
line.get().push("Decompiling " + className);
print();
}
String line = this.line.get().peek();
System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim());
}
@Override
public void startClass(String className) {
workingClass.get().push(className);
line.get().push("Decompiling " + className);
print();
}
@Override
public void startReadingClass(String className) {
workingClass.get().push(className);
line.get().push("Decompiling " + className);
print();
}
@Override
public void startMethod(String methodName) {
String className = workingClass.get().peek();
line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" ")));
print();
}
@Override
public void startClass(String className) {
workingClass.get().push(className);
line.get().push("Decompiling " + className);
print();
}
@Override
public void endMethod() {
line.get().pop();
print();
}
@Override
public void startMethod(String methodName) {
String className = workingClass.get().peek();
line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" ")));
print();
}
@Override
public void endClass() {
line.get().pop();
workingClass.get().pop();
print();
}
@Override
public void endMethod() {
line.get().pop();
print();
}
@Override
public void startWriteClass(String className) {
line.get().push("Writing " + className);
print();
}
@Override
public void endClass() {
line.get().pop();
workingClass.get().pop();
print();
}
@Override
public void endWriteClass() {
line.get().pop();
print();
}
@Override
public void startWriteClass(String className) {
line.get().push("Writing " + className);
print();
}
@Override
public void endReadingClass() {
line.get().pop();
workingClass.get().pop();
print();
}
@Override
public void endWriteClass() {
line.get().pop();
print();
}
@Override
public void endReadingClass() {
line.get().pop();
workingClass.get().pop();
print();
}
}

View file

@ -24,11 +24,11 @@
package net.fabricmc.loom.task.fernflower;
import net.fabricmc.fernflower.api.IFabricResultSaver;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import java.io.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@ -42,108 +42,136 @@ import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
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.
*/
public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver {
private final Supplier<File> output;
private final Supplier<File> lineMapFile;
private final Supplier<File> output;
private final Supplier<File> lineMapFile;
public Map<String, ZipOutputStream> outputStreams = new HashMap<>();
public Map<String, ExecutorService> saveExecutors = new HashMap<>();
public PrintWriter lineMapWriter;
public Map<String, ZipOutputStream> outputStreams = new HashMap<>();
public Map<String, ExecutorService> saveExecutors = new HashMap<>();
public PrintWriter lineMapWriter;
public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) {
this.output = output;
this.lineMapFile = lineMapFile;
}
public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) {
this.output = output;
this.lineMapFile = lineMapFile;
}
@Override
public void createArchive(String path, String archiveName, Manifest manifest) {
String key = path + "/" + archiveName;
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
public void createArchive(String path, String archiveName, Manifest manifest) {
String key = path + "/" + archiveName;
File file = output.get();
@Override
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) {
this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null);
}
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);
}
@Override
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) {
String key = path + "/" + archiveName;
ExecutorService executor = saveExecutors.get(key);
executor.submit(() -> {
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());
}
});
}
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
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 saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) {
this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null);
}
//@formatter:off
@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) { }
//@formatter:on
@Override
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) {
String key = path + "/" + archiveName;
ExecutorService executor = saveExecutors.get(key);
executor.submit(() -> {
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
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;
import java.io.File;
import java.io.IOException;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import java.io.File;
import java.io.IOException;
public class Checksum {
private static final Logger log = Logging.getLogger(Checksum.class);
@ -40,18 +40,22 @@ public class Checksum {
if (file == null) {
return false;
}
try {
//noinspection deprecation
HashCode hash = Files.asByteSource(file).hash(Hashing.sha1());
StringBuilder builder = new StringBuilder();
for (Byte hashBytes : hash.asBytes()) {
builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1));
}
log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?");
return builder.toString().equals(checksum);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}

View file

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

View file

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

View file

@ -24,33 +24,8 @@
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.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@ -60,8 +35,21 @@ import java.util.Set;
import java.util.function.Consumer;
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;
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) {
if(object instanceof File){
if (object instanceof File) {
object = project.files(object);
}
project.getDependencies().add(target, object);
}
public void register(LoomDependencyManager dependencyManager){
public void register(LoomDependencyManager dependencyManager) {
this.dependencyManager = dependencyManager;
}
@ -132,14 +121,17 @@ public abstract class DependencyProvider {
public Optional<File> resolveFile() {
Set<File> files = resolve();
if (files.isEmpty()) {
return Optional.empty();
} else if (files.size() > 1) {
StringBuilder builder = new StringBuilder(this.toString());
builder.append(" resolves to more than one file:");
for (File f : files) {
builder.append("\n\t-").append(f.getAbsolutePath());
}
throw new RuntimeException(builder.toString());
} else {
return files.stream().findFirst();
@ -151,11 +143,11 @@ public abstract class DependencyProvider {
return getDepString();
}
public String getDepString(){
public String getDepString() {
return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion();
}
public String getResolvedDepString(){
public String getResolvedDepString() {
return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion();
}
}
@ -178,7 +170,6 @@ public abstract class DependencyProvider {
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());
//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);
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
classifierToFile.put("", shortest);
int start = shortestName.length();
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
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
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
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();
} else {
name = json.get("id").getAsString();
}
version = json.get("version").getAsString();
} else {
//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
* SOFTWARE.
*/
package net.fabricmc.loom.util;
import java.io.File;
@ -29,21 +30,18 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import com.google.common.io.Files;
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 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()}
*
* @throws IOException If an exception occurs during the process
*/
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 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 quiet Whether to only print warnings (when <code>true</code>) or everything
*
* @throws IOException If an exception occurs during the process
*/
public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException {
HttpURLConnection connection = (HttpURLConnection) from.openConnection();
//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
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
connection.setRequestProperty("Accept-Encoding", "gzip");
@ -80,21 +82,29 @@ public class DownloadUtil {
connection.connect();
int code = connection.getResponseCode();
if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
//Didn't get what we expected
throw new IOException(connection.getResponseMessage());
}
long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1);
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
}
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);
} catch (IOException e) {
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)
if (modifyTime > 0) to.setLastModified(modifyTime);
if (modifyTime > 0) {
to.setLastModified(modifyTime);
}
//Save the ETag (if we know it)
String eTag = connection.getHeaderField("ETag");
if (eTag != null) {
//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);
}
}
/**
* 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
*
* @return The (uncreated) ETag file for the given 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 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
*/
private static String loadETag(File to, Logger logger) {
File eTagFile = getETagFile(to);
if (!eTagFile.exists()) return null;
if (!eTagFile.exists()) {
return null;
}
try {
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 eTag The ETag to be saved
@ -154,8 +170,12 @@ public class DownloadUtil {
*/
private static void saveETag(File to, String eTag, Logger logger) {
File eTagFile = getETagFile(to);
try {
if (!eTagFile.exists()) eTagFile.createNewFile();
if (!eTagFile.exists()) {
eTagFile.createNewFile();
}
Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag);
} catch (IOException 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
*
* @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate
*/
private static String toNiceSize(long bytes) {
@ -192,8 +211,9 @@ public class DownloadUtil {
}
File etagFile = getETagFile(file);
if (etagFile.exists()) {
etagFile.delete();
}
}
}
}

View file

@ -24,23 +24,23 @@
package net.fabricmc.loom.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
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.
public class GradleSupport {
public static RegularFileProperty getfileProperty(Project project){
public static RegularFileProperty getfileProperty(Project project) {
try {
//First try the new method, if that fails fall back.
return getfilePropertyModern(project);
} catch (Exception e){
} catch (Exception e) {
//Nope
}
return getfilePropertyLegacy(project);
}
@ -51,7 +51,7 @@ public class GradleSupport {
return (RegularFileProperty) method.invoke(objectFactory);
}
private static RegularFileProperty getfilePropertyLegacy(Project project){
private static RegularFileProperty getfilePropertyLegacy(Project project) {
return project.getLayout().fileProperty();
}
}

View file

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

View file

@ -24,138 +24,160 @@
package net.fabricmc.loom.util;
import net.fabricmc.loom.util.progress.ProgressLogger;
import org.gradle.api.logging.Logger;
import org.objectweb.asm.*;
import static java.text.MessageFormat.format;
import java.io.*;
import java.nio.file.*;
import java.io.BufferedReader;
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.util.HashMap;
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.
* Created by covers1624 on 18/02/19.
*/
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 (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) {
RClass clazz = null;
String line = null;
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);
}
}
try {
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
public void process(ProgressLogger logger, Path input, Path output) throws IOException {
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);
}
String[] segs = line.trim().split("\t");
int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped.
if (dollarPos >= 0) {
idx = idx.substring(0, dollarPos);
}
if (lineMap.containsKey(idx)) {
try (InputStream is = Files.newInputStream(file)) {
ClassReader reader = new ClassReader(is);
ClassWriter writer = new ClassWriter(0);
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]));
}
reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0);
Files.write(dst, writer.toByteArray());
}
}
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);
}
}
} else {
Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING);
}
public void process(ProgressLogger logger, Path input, Path output) throws IOException {
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) {
super(api, classVisitor);
this.rClass = rClass;
}
String idx = rel.substring(0, rel.length() - 6);
@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);
}
}
};
}
}
if (logger != null) {
logger.progress("Remapping " + idx);
}
private static class RClass {
int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped.
private final String name;
private int maxLine;
private int maxLineDest;
private Map<Integer, Integer> lineMap = new HashMap<>();
if (dollarPos >= 0) {
idx = idx.substring(0, dollarPos);
}
private RClass(String name) {
this.name = name;
}
}
if (lineMap.containsKey(idx)) {
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;
import com.google.gson.JsonObject;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.DependencyProvider.DependencyInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
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.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import java.io.File;
import java.util.*;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.loom.util.DependencyProvider.DependencyInfo;
public class LoomDependencyManager {
private static class ProviderList {
@ -50,27 +55,30 @@ public class LoomDependencyManager {
private List<DependencyProvider> dependencyProviderList = new ArrayList<>();
public void addProvider(DependencyProvider provider){
if(dependencyProviderList.contains(provider)){
public void addProvider(DependencyProvider provider) {
if (dependencyProviderList.contains(provider)) {
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");
}
provider.register(this);
dependencyProviderList.add(provider);
}
public <T> T getProvider(Class<T> clazz){
for(DependencyProvider provider : dependencyProviderList){
if(provider.getClass() == clazz){
public <T> T getProvider(Class<T> clazz) {
for (DependencyProvider provider : dependencyProviderList) {
if (provider.getClass() == clazz) {
return (T) provider;
}
}
return null;
}
public void handleDependencies(Project project){
public void handleDependencies(Project project) {
List<Runnable> afterTasks = new ArrayList<>();
MappingsProvider mappingsProvider = null;
@ -80,7 +88,7 @@ public class LoomDependencyManager {
Map<String, ProviderList> providerListMap = new HashMap<>();
List<ProviderList> targetProviders = new ArrayList<>();
for(DependencyProvider provider : dependencyProviderList){
for (DependencyProvider provider : dependencyProviderList) {
providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> {
ProviderList list = new ProviderList(k);
targetProviders.add(list);
@ -101,6 +109,7 @@ public class LoomDependencyManager {
configuration.getDependencies().forEach(dependency -> {
for (DependencyProvider provider : list.providers) {
DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration);
try {
provider.provide(info, project, extension, afterTasks::add);
} catch (Exception e) {
@ -114,13 +123,7 @@ public class LoomDependencyManager {
String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion;
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
ModCompileRemapper.remapDependencies(
project, mappingsKey, extension,
project.getConfigurations().getByName(entry.getSourceConfiguration()),
project.getConfigurations().getByName(entry.getRemappedConfiguration()),
project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())),
afterTasks::add
);
ModCompileRemapper.remapDependencies(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()) {
DependencyInfo info = DependencyInfo.create(project, dependency, configuration);
for (File input : info.resolve()) {
if (seenFiles.add(input)) {
ModProcessor.readInstallerJson(input, project);
if (extension.getInstallerJson() != null) {
project.getLogger().info("Found installer JSON in " + info);
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();
Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES);
Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor");
@ -171,16 +176,15 @@ public class LoomDependencyManager {
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();
long count = project.getRepositories().stream()
.filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
.map(artifactRepository -> (MavenArtifactRepository) artifactRepository)
.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()));
}
}
});
}

View file

@ -24,32 +24,28 @@
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.IOException;
import java.nio.file.Path;
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 {
String fromM = "official";
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MappingsProvider mappingsProvider = extension.getMappingsProvider();
Path[] classpath = mapProvider.getMapperPaths().stream()
.map(File::toPath)
.toArray(Path[]::new);
Path[] classpath = mapProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
Path input = jarProvider.getMergedJar().toPath();
Path outputMapped = mapProvider.getMappedJar().toPath();
@ -60,11 +56,7 @@ public class MapJarsTiny {
project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
TinyRemapper remapper = TinyRemapper.newRemapper()
.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.build();
TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).renameInvalidLocals(true).rebuildSourceFilenames(true).build();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
outputConsumer.addNonClassFiles(input);

View file

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

View file

@ -24,15 +24,6 @@
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.IOException;
import java.io.InputStreamReader;
@ -41,86 +32,91 @@ import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
public final class MixinRefmapHelper {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
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) {
File output = outputPath.toFile();
Set<String> mixinFilenames = findMixins(output, true);
if (mixinFilenames.size() > 0) {
return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
@Override
protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class);
if (mixinFilenames.size() > 0) {
return ZipUtil.transformEntries(
output,
mixinFilenames.stream()
.map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") {
@Override
protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class);
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;
}
}
if (!json.has("refmap")) {
json.addProperty("refmap", filename);
}
private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) {
// first, identify all of the mixin files
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.has("minVersion") && mixinVersion != null) {
json.addProperty("minVersion", mixinVersion);
}
if (json != null) {
boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray();
boolean hasClient = json.has("client") && json.get("client").isJsonArray();
boolean hasServer = json.has("server") && json.get("server").isJsonArray();
return GSON.toJson(json);
}
})).toArray(ZipEntryTransformerEntry[]::new));
} else {
return false;
}
}
if (json.has("package") && (hasMixins || hasClient || hasServer)) {
if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) {
mixinFilename.add(entry.getName());
}
}
}
} catch (Exception e) {
// ...
}
}
});
return mixinFilename;
}
private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) {
// first, identify all of the mixin files
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);
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;
}
if (json != null) {
boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray();
boolean hasClient = json.has("client") && json.get("client").isJsonArray();
boolean hasServer = json.has("server") && json.get("server").isJsonArray();
if (json.has("package") && (hasMixins || hasClient || hasServer)) {
if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) {
mixinFilename.add(entry.getName());
}
}
}
} catch (Exception e) {
// ...
}
}
});
return mixinFilename;
}
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;
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.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
@ -40,10 +44,7 @@ import org.gradle.api.logging.Logger;
import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import net.fabricmc.loom.LoomGradleExtension;
public class ModCompileRemapper {
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) {
File input = artifact.getFile();
@ -112,15 +113,18 @@ public class ModCompileRemapper {
project.getLogger().info(":providing " + notation);
DependencyHandler dependencies = project.getDependencies();
Dependency dep = dependencies.module(notation);
if (dep instanceof ModuleDependency) {
((ModuleDependency) dep).setTransitive(false);
}
dependencies.add(regularCompile.getName(), dep);
}
private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) {
File input = artifact.getFile();
File output = new File(modStore, remappedFilename + ".jar");
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
try {
@ -129,7 +133,7 @@ public class ModCompileRemapper {
throw new RuntimeException("Failed to remap mod", e);
}
if (!output.exists()){
if (!output.exists()) {
throw new RuntimeException("Failed to remap mod");
}
@ -142,10 +146,10 @@ public class ModCompileRemapper {
}
private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) {
@SuppressWarnings ("unchecked")
ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
.forComponents(artifact.getId().getComponentIdentifier())//
.withArtifacts(JvmLibrary.class, SourcesArtifact.class);
for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) {
for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) {
if (srcArtifact instanceof ResolvedArtifactResult) {
@ -153,6 +157,7 @@ public class ModCompileRemapper {
}
}
}
return null;
}

View file

@ -24,23 +24,6 @@
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.IOException;
import java.io.InputStream;
@ -54,18 +37,39 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
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 {
private static final Gson GSON = new Gson();
public static void processMod(File input, File output, Project project, Configuration config) throws IOException {
if(output.exists()){
if (output.exists()) {
output.delete();
}
remapJar(input, output, project);
//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);
}
//Always strip the nested jars
stripNestedJars(output);
}
@ -77,15 +81,20 @@ public class ModProcessor {
private static void handleNestedJars(File input, Project project, Configuration config) throws IOException {
JarFile jarFile = new JarFile(input);
JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json");
if(modJsonEntry == null){
if (modJsonEntry == null) {
return;
}
try(InputStream inputStream = jarFile.getInputStream(modJsonEntry)){
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
if(json == null || !json.has("jars")){
if (json == null || !json.has("jars")) {
return;
}
JsonArray jsonArray = json.getAsJsonArray("jars");
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
String fileName = jsonObject.get("file").getAsString();
@ -99,19 +108,22 @@ public class ModProcessor {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
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()));
}
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);
}
File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/")));
processMod(nestedFile, remappedFile, project, config);
if(!remappedFile.exists()){
if (!remappedFile.exists()) {
throw new RuntimeException("Failed to find processed nested jar");
}
@ -119,7 +131,7 @@ public class ModProcessor {
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.
ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
@Override
@ -143,29 +155,22 @@ public class ModProcessor {
Path mappings = mappingsFile.toPath();
Path inputPath = input.getAbsoluteFile().toPath();
Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath();
Path[] mcDeps = mappedProvider.getMapperPaths().stream()
.map(File::toPath)
.toArray(Path[]::new);
Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
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 + ")");
TinyRemapper remapper = TinyRemapper.newRemapper()
.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM))
.build();
TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).build();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) {
outputConsumer.addNonClassFiles(inputPath);
@ -178,12 +183,12 @@ public class ModProcessor {
remapper.finish();
}
if(!output.exists()){
if (!output.exists()) {
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 {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
String launchMethod = extension.getLoaderLaunchMethod();
@ -193,8 +198,10 @@ public class ModProcessor {
try (JarFile jarFile = new JarFile(file)) {
ZipEntry entry = null;
if (!launchMethod.isEmpty()) {
entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json");
if (entry == null) {
project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back");
}
@ -203,6 +210,7 @@ public class ModProcessor {
if (entry == null) {
entry = jarFile.getEntry("fabric-installer.json");
priority++;
if (entry == null) {
return;
}

View file

@ -24,28 +24,6 @@
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.IOException;
import java.nio.file.Path;
@ -56,8 +34,28 @@ import java.util.Locale;
import java.util.Set;
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();
public static boolean addNestedJars(Project project, Path modJarPath) {
@ -74,6 +72,7 @@ public class NestedJars {
protected String transform(ZipEntry zipEntry, String input) throws IOException {
JsonObject json = GSON.fromJson(input, JsonObject.class);
JsonArray nestedJars = json.getAsJsonArray("jars");
if (nestedJars == null || !json.has("jars")) {
nestedJars = new JsonArray();
}
@ -96,6 +95,7 @@ public class NestedJars {
Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE);
DependencySet dependencies = configuration.getDependencies();
for (Dependency dependency : dependencies) {
if (dependency instanceof ProjectDependency) {
ProjectDependency projectDependency = (ProjectDependency) dependency;
@ -116,27 +116,32 @@ public class NestedJars {
fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project));
}
}
for (File file : fileList) {
if (!file.exists()) {
throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath());
}
if (file.isDirectory() || !file.getName().endsWith(".jar")) {
throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath());
}
}
return fileList;
}
//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<>();
Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE);
DependencySet dependencies = configuration.getDependencies();
for (Dependency dependency : dependencies) {
if (dependency instanceof ProjectDependency) {
ProjectDependency projectDependency = (ProjectDependency) dependency;
Project dependencyProject = projectDependency.getDependencyProject();
for (Task task : dependencyProject.getTasksByName("remapJar", false)) {
if (task instanceof RemapJarTask) {
remapTasks.add((RemapJarTask) task);
@ -144,29 +149,36 @@ public class NestedJars {
}
}
}
return remapTasks;
}
//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<>();
for(File file : files){
for (File file : files) {
//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);
File tempDir = new File(extension.getUserCache(), "temp/modprocessing");
if(!tempDir.exists()){
if (!tempDir.exists()) {
tempDir.mkdirs();
}
File tempFile = new File(tempDir, file.getName());
if(tempFile.exists()){
if (tempFile.exists()) {
tempFile.delete();
}
try {
FileUtils.copyFile(file, tempFile);
} catch (IOException e) {
throw new RuntimeException("Failed to copy file", e);
}
ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes());
fileList.add(tempFile);
} else {
@ -174,11 +186,12 @@ public class NestedJars {
fileList.add(file);
}
}
return fileList;
}
//Generates a barebones mod for a dependency
private static String getMod(Dependency dependency){
private static String getMod(Dependency dependency) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("schemaVersion", 1);
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 static String getOS() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return "windows";
} else if (osName.contains("mac")) {

View file

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

View file

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

View file

@ -24,25 +24,27 @@
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.IOException;
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) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
File projectDir = project.file(".idea");
if(!projectDir.exists()){
if (!projectDir.exists()) {
return;
}
try {
generate(project);
} catch (IOException e) {
@ -50,6 +52,7 @@ public class SetupIntelijRunConfigs {
}
File runDir = new File(project.getRootDir(), extension.runDir);
if (!runDir.exists()) {
runDir.mkdirs();
}
@ -57,7 +60,7 @@ public class SetupIntelijRunConfigs {
private static void generate(Project project) throws IOException {
//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);
MinecraftAssetsProvider.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 serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml");
if(!runConfigsDir.exists()){
if (!runConfigsDir.exists()) {
runConfigsDir.mkdirs();
}
String clientRunConfig = RunConfig.clientRunConfig(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);
if(!serverRunConfigs.exists())
}
if (!serverRunConfigs.exists()) {
FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8);
}
}
}

View file

@ -24,31 +24,26 @@
package net.fabricmc.loom.util;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
import net.fabricmc.mappings.*;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.stitch.util.StitchUtil;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.cadixdev.lorenz.MappingSet;
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.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.gradle.api.Project;
import java.io.*;
import java.net.URI;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.providers.MappingsProvider;
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.stitch.util.StitchUtil;
public class SourceRemapper {
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()) {
m.getClassPath().add(file.toPath());
}
if (!toNamed) {
for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
m.getClassPath().add(file.toPath());
}
}
for (Path file : extension.getUnmappedMods()) {
if (Files.isRegularFile(file)) {
m.getClassPath().add(file);
@ -104,6 +101,7 @@ public class SourceRemapper {
}
source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
try {
com.google.common.io.Files.move(destination, source);
} catch (IOException e) {
@ -113,6 +111,7 @@ public class SourceRemapper {
Path srcPath = source.toPath();
boolean isSrcTmp = false;
if (!source.isDirectory()) {
// create tmp directory
isSrcTmp = true;
@ -144,27 +143,27 @@ public class SourceRemapper {
if (isSrcTmp) {
Files.walkFileTree(srcPath, new DeletingFileVisitor());
}
}
private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
Files.walk(from).forEach(path -> {
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 void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
Files.walk(from).forEach(path -> {
Path targetPath = to.resolve(from.relativize(path).toString());
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;
}
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) {
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 {
private final Mappings m;
@ -179,35 +178,27 @@ public class SourceRemapper {
@Override
public MappingSet read(final MappingSet mappings) {
for (ClassEntry entry : m.getClassEntries()) {
mappings.getOrCreateClassMapping(entry.get(from))
.setDeobfuscatedName(entry.get(to));
mappings.getOrCreateClassMapping(entry.get(from)).setDeobfuscatedName(entry.get(to));
}
for (FieldEntry entry : m.getFieldEntries()) {
EntryTriple fromEntry = entry.get(from);
EntryTriple toEntry = entry.get(to);
mappings.getOrCreateClassMapping(fromEntry.getOwner())
.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
}
for (MethodEntry entry : m.getMethodEntries()) {
EntryTriple fromEntry = entry.get(from);
EntryTriple toEntry = entry.get(to);
mappings.getOrCreateClassMapping(fromEntry.getOwner())
.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc())
.setDeobfuscatedName(toEntry.getName());
mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
}
return mappings;
}
@Override
public void close() throws IOException {
}
public void close() throws IOException { }
}
}

View file

@ -24,63 +24,66 @@
package net.fabricmc.loom.util;
import net.fabricmc.mappings.Mappings;
import org.gradle.api.logging.Logging;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.nio.file.*;
import java.nio.file.FileSystems;
import java.nio.file.Files;
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.Map;
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 WatchService service;
private final Map<Path, WatchKey> pathsObserved = new HashMap<>();
private final Map<Path, Boolean> changeCache = new HashMap<>();
private final WatchService service;
private final Map<Path, WatchKey> pathsObserved = new HashMap<>();
private StaticPathWatcher() {
try {
service = FileSystems.getDefault().newWatchService();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private StaticPathWatcher() {
try {
service = FileSystems.getDefault().newWatchService();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public boolean hasFileChanged(Path filePath) {
if(!Files.exists(filePath)){
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);
}
}
}
public boolean hasFileChanged(Path filePath) {
if (!Files.exists(filePath)) {
return 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
));
WatchKey key;
return true;
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
return false;
}
}
}
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();
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;
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.MemberInstance;
public class TinyRemapperMappingsHelper {
private TinyRemapperMappingsHelper() {
}
private TinyRemapperMappingsHelper() { }
public static IMappingProvider create(Mappings mappings, String from, String to) {
return (classMap, fieldMap, methodMap) -> {

View file

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

View file

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

View file

@ -24,13 +24,13 @@
package net.fabricmc.loom.util.progress;
import org.gradle.api.Project;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.gradle.api.Project;
/**
* Wrapper to ProgressLogger internal API
* Wrapper to ProgressLogger internal API.
*/
public class ProgressLogger {
private final Object logger;
@ -54,6 +54,7 @@ public class ProgressLogger {
private static Class<?> getFactoryClass() {
Class<?> progressLoggerFactoryClass = null;
try {
//Gradle 2.14 and higher
progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory");
@ -65,6 +66,7 @@ public class ProgressLogger {
// Unsupported Gradle version
}
}
return progressLoggerFactoryClass;
}
@ -73,9 +75,10 @@ public class ProgressLogger {
try {
return logger.getClass().getMethod(methodName, args);
} catch (NoSuchMethodException ignored) {
//Nope
}
}
return null;
}
@ -85,14 +88,15 @@ public class ProgressLogger {
method.setAccessible(true);
return method.invoke(logger, args);
} catch (IllegalAccessException | InvocationTargetException ignored) {
//Nope
}
}
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 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.
* <p>
* <p>This must be called before {@link #started()}.
* Sets the description of the operation. This should be a full, stand-alone description of the operation.
*
* <p>This must be called before {@link #started()}
*
* @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.
* <p>
* Sets the short description of the operation. This is used in place of the full description when display space is limited.
*
* <p>This must be called before {@link #started()}
*
* @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.
* <p>
*
* <p>If not specified, no logging header is logged.
*
* @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.
*
* @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() {
invoke(completed);