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:
		
							parent
							
								
									2bd339241f
								
							
						
					
					
						commit
						f85daec559
					
				
					 59 changed files with 2129 additions and 1655 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -17,4 +17,6 @@ | ||||||
| !/LICENSE | !/LICENSE | ||||||
| !/README.md | !/README.md | ||||||
| !/settings.gradle | !/settings.gradle | ||||||
| !/Jenkinsfile | !/Jenkinsfile | ||||||
|  | !/.travis.yml | ||||||
|  | !/checkstyle.xml | ||||||
							
								
								
									
										12
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | language: java | ||||||
|  | install: true | ||||||
|  | 
 | ||||||
|  | jdk: | ||||||
|  |   - openjdk8 | ||||||
|  | 
 | ||||||
|  | script: | ||||||
|  |   - chmod +x gradlew | ||||||
|  |   - ./gradlew check build test --stacktrace | ||||||
|  | 
 | ||||||
|  | notifications: | ||||||
|  |   email: false | ||||||
							
								
								
									
										16
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								build.gradle
									
									
									
									
									
								
							|  | @ -5,6 +5,7 @@ plugins { | ||||||
| 	id 'idea' | 	id 'idea' | ||||||
| 	id 'eclipse' | 	id 'eclipse' | ||||||
| 	id 'groovy' | 	id 'groovy' | ||||||
|  | 	id 'checkstyle' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sourceCompatibility = 1.8 | sourceCompatibility = 1.8 | ||||||
|  | @ -60,6 +61,12 @@ dependencies { | ||||||
| 	testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") | 	testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | configurations.all { | ||||||
|  | 	resolutionStrategy { | ||||||
|  | 		force 'org.codehaus.groovy:groovy-all:2.4.12' | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| jar { | jar { | ||||||
| 	manifest { | 	manifest { | ||||||
| 		attributes 'Implementation-Version': version + " Build(" + build + ")" | 		attributes 'Implementation-Version': version + " Build(" + build + ")" | ||||||
|  | @ -82,6 +89,15 @@ license { | ||||||
| 	exclude '**/loom/util/DownloadUtil.java' | 	exclude '**/loom/util/DownloadUtil.java' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | checkstyle { | ||||||
|  | 	configFile = file("checkstyle.xml") | ||||||
|  | 	toolVersion = '8.25' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | checkstyleMain { | ||||||
|  | 	logging.setLevel(LogLevel.LIFECYCLE) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| gradlePlugin { | gradlePlugin { | ||||||
| 	plugins { | 	plugins { | ||||||
| 		fabricLoom { | 		fabricLoom { | ||||||
|  |  | ||||||
							
								
								
									
										162
									
								
								checkstyle.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								checkstyle.xml
									
									
									
									
									
										Normal 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="(?<=\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="(?<=\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> | ||||||
|  | @ -24,13 +24,16 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom; | package net.fabricmc.loom; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Optional; | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.function.Predicate; | ||||||
|  | 
 | ||||||
| import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||||
| import groovy.util.Node; | import groovy.util.Node; | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftProvider; |  | ||||||
| import net.fabricmc.loom.task.RemapJarTask; |  | ||||||
| import net.fabricmc.loom.task.RemapSourcesJarTask; |  | ||||||
| import net.fabricmc.loom.util.*; |  | ||||||
| import org.gradle.api.Plugin; | import org.gradle.api.Plugin; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.Task; | import org.gradle.api.Task; | ||||||
|  | @ -54,13 +57,16 @@ import org.gradle.api.tasks.scala.ScalaCompile; | ||||||
| import org.gradle.plugins.ide.eclipse.model.EclipseModel; | import org.gradle.plugins.ide.eclipse.model.EclipseModel; | ||||||
| import org.gradle.plugins.ide.idea.model.IdeaModel; | import org.gradle.plugins.ide.idea.model.IdeaModel; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
| import java.io.IOException; | import net.fabricmc.loom.providers.MinecraftProvider; | ||||||
| import java.util.HashSet; | import net.fabricmc.loom.task.RemapJarTask; | ||||||
| import java.util.Map; | import net.fabricmc.loom.task.RemapSourcesJarTask; | ||||||
| import java.util.Optional; | import net.fabricmc.loom.util.Constants; | ||||||
| import java.util.Set; | import net.fabricmc.loom.util.GroovyXmlUtil; | ||||||
| import java.util.function.Predicate; | import net.fabricmc.loom.util.LoomDependencyManager; | ||||||
|  | import net.fabricmc.loom.util.NestedJars; | ||||||
|  | import net.fabricmc.loom.util.RemappedConfigurationEntry; | ||||||
|  | import net.fabricmc.loom.util.SetupIntelijRunConfigs; | ||||||
| 
 | 
 | ||||||
| public class AbstractPlugin implements Plugin<Project> { | public class AbstractPlugin implements Plugin<Project> { | ||||||
| 	protected Project project; | 	protected Project project; | ||||||
|  | @ -116,6 +122,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 			compileModsMappedConfig.setTransitive(false); // Don't get transitive deps of already remapped mods | 			compileModsMappedConfig.setTransitive(false); // Don't get transitive deps of already remapped mods | ||||||
| 
 | 
 | ||||||
| 			extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration()); | 			extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration()); | ||||||
|  | 
 | ||||||
| 			if (entry.isOnModCompileClasspath()) { | 			if (entry.isOnModCompileClasspath()) { | ||||||
| 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration()); | 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration()); | ||||||
| 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration()); | 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration()); | ||||||
|  | @ -137,15 +144,17 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		configureScala(); | 		configureScala(); | ||||||
| 
 | 
 | ||||||
| 		Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | 		Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | ||||||
|  | 
 | ||||||
| 		for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | 		for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | ||||||
| 			Project project = entry.getKey(); | 			Project project = entry.getKey(); | ||||||
| 			Set<Task> taskSet = entry.getValue(); | 			Set<Task> taskSet = entry.getValue(); | ||||||
|  | 
 | ||||||
| 			for (Task task : taskSet) { | 			for (Task task : taskSet) { | ||||||
| 				if (task instanceof JavaCompile | 				if (task instanceof JavaCompile && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { | ||||||
| 						&& !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { |  | ||||||
| 					JavaCompile javaCompileTask = (JavaCompile) task; | 					JavaCompile javaCompileTask = (JavaCompile) task; | ||||||
| 					javaCompileTask.doFirst(task1 -> { | 					javaCompileTask.doFirst(task1 -> { | ||||||
| 						project.getLogger().lifecycle(":setting java compiler args"); | 						project.getLogger().lifecycle(":setting java compiler args"); | ||||||
|  | 
 | ||||||
| 						try { | 						try { | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | 							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | 							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | ||||||
|  | @ -166,30 +175,31 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		return project; | 		return project; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|     protected void configureScala() { | 	protected void configureScala() { | ||||||
|         project.afterEvaluate(proj -> { | 		project.afterEvaluate(proj -> { | ||||||
|             if (project.getPluginManager().hasPlugin("scala")) { | 			if (project.getPluginManager().hasPlugin("scala")) { | ||||||
|                 ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); | 				ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); | ||||||
|                 LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|                 project.getLogger().warn(":configuring scala compilation processing"); | 				project.getLogger().warn(":configuring scala compilation processing"); | ||||||
|                 try { | 
 | ||||||
|                     task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | 				try { | ||||||
|                     task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | 					task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | ||||||
|                     task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); | 					task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | ||||||
|                     task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); | 					task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); | ||||||
|                 } catch (IOException e) { | 					task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); | ||||||
|                     e.printStackTrace(); | 				} catch (IOException e) { | ||||||
|                 } | 					e.printStackTrace(); | ||||||
|             } | 				} | ||||||
|         }); | 			} | ||||||
|     } | 		}); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Permit to add a Maven repository to a target project | 	 * Permit to add a Maven repository to a target project. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param target The garget project | 	 * @param target The garget project | ||||||
| 	 * @param name   The name of the repository | 	 * @param name The name of the repository | ||||||
| 	 * @param url    The URL of the repository | 	 * @param url The URL of the repository | ||||||
| 	 * @return An object containing the name and the URL of the repository that can be modified later | 	 * @return An object containing the name and the URL of the repository that can be modified later | ||||||
| 	 */ | 	 */ | ||||||
| 	public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) { | 	public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) { | ||||||
|  | @ -200,7 +210,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add Minecraft dependencies to IDE dependencies | 	 * Add Minecraft dependencies to IDE dependencies. | ||||||
| 	 */ | 	 */ | ||||||
| 	protected void configureIDEs() { | 	protected void configureIDEs() { | ||||||
| 		// IDEA | 		// IDEA | ||||||
|  | @ -236,6 +246,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		if (dep instanceof ResolvedDependencyResult) { | 		if (dep instanceof ResolvedDependencyResult) { | ||||||
| 			if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) { | 			if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) { | ||||||
| 				ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId()); | 				ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId()); | ||||||
|  | 
 | ||||||
| 				if (predicate.test(mci)) { | 				if (predicate.test(mci)) { | ||||||
| 					addModule(project, configuration, dep); | 					addModule(project, configuration, dep); | ||||||
| 					found = true; | 					found = true; | ||||||
|  | @ -251,7 +262,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add Minecraft dependencies to compile time | 	 * Add Minecraft dependencies to compile time. | ||||||
| 	 */ | 	 */ | ||||||
| 	protected void configureCompile() { | 	protected void configureCompile() { | ||||||
| 		JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); | 		JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); | ||||||
|  | @ -264,12 +275,18 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 
 | 
 | ||||||
| 		// Add Mixin dependencies | 		// Add Mixin dependencies | ||||||
| 		Project p = project; | 		Project p = project; | ||||||
|  | 
 | ||||||
| 		while (true) { | 		while (true) { | ||||||
| 			boolean found = false; | 			boolean found = false; | ||||||
|  | 
 | ||||||
| 			for (DependencyResult dep : p.getBuildscript().getConfigurations().getByName("classpath").getIncoming().getResolutionResult().getRoot().getDependencies()) { | 			for (DependencyResult dep : p.getBuildscript().getConfigurations().getByName("classpath").getIncoming().getResolutionResult().getRoot().getDependencies()) { | ||||||
| 				found = findAndAddModule(project, "annotationProcessor", dep, (mci) -> ("net.fabricmc".equals(mci.getGroup()) && "fabric-mixin-compile-extensions".equals(mci.getModule()))); | 				found = findAndAddModule(project, "annotationProcessor", dep, (mci) -> ("net.fabricmc".equals(mci.getGroup()) && "fabric-mixin-compile-extensions".equals(mci.getModule()))); | ||||||
| 			} | 			} | ||||||
| 			if (found || AbstractPlugin.isRootProject(p)) break; | 
 | ||||||
|  | 			if (found || AbstractPlugin.isRootProject(p)) { | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			p = p.getRootProject(); | 			p = p.getRootProject(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -330,6 +347,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 				RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar"); | 				RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar"); | ||||||
| 
 | 
 | ||||||
| 				assert remapJarTask != null; | 				assert remapJarTask != null; | ||||||
|  | 
 | ||||||
| 				if (!remapJarTask.getInput().isPresent()) { | 				if (!remapJarTask.getInput().isPresent()) { | ||||||
| 					jarTask.setClassifier("dev"); | 					jarTask.setClassifier("dev"); | ||||||
| 					remapJarTask.setClassifier(""); | 					remapJarTask.setClassifier(""); | ||||||
|  | @ -344,8 +362,10 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 				project1.getTasks().getByName("build").dependsOn(remapJarTask); | 				project1.getTasks().getByName("build").dependsOn(remapJarTask); | ||||||
| 
 | 
 | ||||||
| 				Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | 				Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | ||||||
|  | 
 | ||||||
| 				for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | 				for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | ||||||
| 					Set<Task> taskSet = entry.getValue(); | 					Set<Task> taskSet = entry.getValue(); | ||||||
|  | 
 | ||||||
| 					for (Task task : taskSet) { | 					for (Task task : taskSet) { | ||||||
| 						if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) { | 						if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) { | ||||||
| 							//Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects | 							//Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects | ||||||
|  | @ -384,6 +404,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 
 | 
 | ||||||
| 				// add modsCompile to maven-publish | 				// add modsCompile to maven-publish | ||||||
| 				PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class); | 				PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class); | ||||||
|  | 
 | ||||||
| 				if (mavenPublish != null) { | 				if (mavenPublish != null) { | ||||||
| 					mavenPublish.publications((publications) -> { | 					mavenPublish.publications((publications) -> { | ||||||
| 						for (Publication publication : publications) { | 						for (Publication publication : publications) { | ||||||
|  | @ -393,15 +414,14 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 										Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies"); | 										Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies"); | ||||||
| 										Set<String> foundArtifacts = new HashSet<>(); | 										Set<String> foundArtifacts = new HashSet<>(); | ||||||
| 
 | 
 | ||||||
| 										GroovyXmlUtil.childrenNodesStream(dependencies) | 										GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> { | ||||||
| 												.filter((n) -> "dependency".equals(n.name())) | 											Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId"); | ||||||
| 												.forEach((n) -> { | 											Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId"); | ||||||
| 													Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId"); | 
 | ||||||
| 													Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId"); | 											if (groupId.isPresent() && artifactId.isPresent()) { | ||||||
| 													if (groupId.isPresent() && artifactId.isPresent()) { | 												foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text()); | ||||||
| 														foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text()); | 											} | ||||||
| 													} | 										}); | ||||||
| 												}); |  | ||||||
| 
 | 
 | ||||||
| 										for (Dependency dependency : compileModsConfig.getAllDependencies()) { | 										for (Dependency dependency : compileModsConfig.getAllDependencies()) { | ||||||
| 											if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) { | 											if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) { | ||||||
|  |  | ||||||
|  | @ -24,28 +24,30 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom; | package net.fabricmc.loom; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  | import java.util.function.BiPredicate; | ||||||
|  | import java.util.function.Function; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  | 
 | ||||||
|  | import javax.annotation.Nullable; | ||||||
|  | 
 | ||||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||||
|  | import org.cadixdev.lorenz.MappingSet; | ||||||
|  | import org.cadixdev.mercury.Mercury; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.artifacts.Configuration; | ||||||
|  | import org.gradle.api.artifacts.Dependency; | ||||||
|  | 
 | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||||
| import net.fabricmc.loom.providers.MinecraftProvider; | import net.fabricmc.loom.providers.MinecraftProvider; | ||||||
| import net.fabricmc.loom.util.LoomDependencyManager; | import net.fabricmc.loom.util.LoomDependencyManager; | ||||||
| import org.cadixdev.lorenz.MappingSet; |  | ||||||
| import org.cadixdev.mercury.Mercury; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.UnknownDomainObjectException; |  | ||||||
| import org.gradle.api.artifacts.Configuration; |  | ||||||
| import org.gradle.api.artifacts.Dependency; |  | ||||||
| import org.gradle.api.artifacts.component.ComponentIdentifier; |  | ||||||
| import org.gradle.api.artifacts.component.ModuleComponentIdentifier; |  | ||||||
| import org.gradle.api.artifacts.result.ResolvedArtifactResult; |  | ||||||
| 
 |  | ||||||
| import javax.annotation.Nullable; |  | ||||||
| import java.io.File; |  | ||||||
| import java.nio.file.Path; |  | ||||||
| import java.util.*; |  | ||||||
| import java.util.function.BiPredicate; |  | ||||||
| import java.util.function.Function; |  | ||||||
| import java.util.function.Supplier; |  | ||||||
| 
 | 
 | ||||||
| public class LoomGradleExtension { | public class LoomGradleExtension { | ||||||
| 	public String runDir = "run"; | 	public String runDir = "run"; | ||||||
|  | @ -87,77 +89,93 @@ public class LoomGradleExtension { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void setInstallerJson(JsonObject object, int priority) { | 	public void setInstallerJson(JsonObject object, int priority) { | ||||||
| 	    if (installerJson == null || priority <= installerJsonPriority) { | 		if (installerJson == null || priority <= installerJsonPriority) { | ||||||
|             this.installerJson = object; | 			this.installerJson = object; | ||||||
|             this.installerJsonPriority = priority; | 			this.installerJsonPriority = priority; | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public JsonObject getInstallerJson() { | 	public JsonObject getInstallerJson() { | ||||||
| 	    return installerJson; | 		return installerJson; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getUserCache() { | 	public File getUserCache() { | ||||||
| 		File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom"); | 		File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom"); | ||||||
|  | 
 | ||||||
| 		if (!userCache.exists()) { | 		if (!userCache.exists()) { | ||||||
| 			userCache.mkdirs(); | 			userCache.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return userCache; | 		return userCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getRootProjectPersistentCache() { | 	public File getRootProjectPersistentCache() { | ||||||
| 		File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache"); | 		File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache"); | ||||||
| 		if(!projectCache.exists()){ | 
 | ||||||
|  | 		if (!projectCache.exists()) { | ||||||
| 			projectCache.mkdirs(); | 			projectCache.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return projectCache; | 		return projectCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getRootProjectBuildCache() { | 	public File getRootProjectBuildCache() { | ||||||
| 		File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache"); | 		File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache"); | ||||||
| 		if(!projectCache.exists()){ | 
 | ||||||
|  | 		if (!projectCache.exists()) { | ||||||
| 			projectCache.mkdirs(); | 			projectCache.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return projectCache; | 		return projectCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getProjectBuildCache() { | 	public File getProjectBuildCache() { | ||||||
| 		File projectCache = new File(project.getBuildDir(), "loom-cache"); | 		File projectCache = new File(project.getBuildDir(), "loom-cache"); | ||||||
| 		if(!projectCache.exists()){ | 
 | ||||||
|  | 		if (!projectCache.exists()) { | ||||||
| 			projectCache.mkdirs(); | 			projectCache.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return projectCache; | 		return projectCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getRemappedModCache() { | 	public File getRemappedModCache() { | ||||||
| 		File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods"); | 		File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods"); | ||||||
|  | 
 | ||||||
| 		if (!remappedModCache.exists()) { | 		if (!remappedModCache.exists()) { | ||||||
| 			remappedModCache.mkdir(); | 			remappedModCache.mkdir(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return remappedModCache; | 		return remappedModCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getNestedModCache() { | 	public File getNestedModCache() { | ||||||
| 		File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods"); | 		File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods"); | ||||||
|  | 
 | ||||||
| 		if (!nestedModCache.exists()) { | 		if (!nestedModCache.exists()) { | ||||||
| 			nestedModCache.mkdir(); | 			nestedModCache.mkdir(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return nestedModCache; | 		return nestedModCache; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getNativesJarStore(){ | 	public File getNativesJarStore() { | ||||||
| 		File natives = new File(getUserCache(), "natives/jars"); | 		File natives = new File(getUserCache(), "natives/jars"); | ||||||
| 		if(!natives.exists()) { | 
 | ||||||
|  | 		if (!natives.exists()) { | ||||||
| 			natives.mkdirs(); | 			natives.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return natives; | 		return natives; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public File getNativesDirectory(){ | 	public File getNativesDirectory() { | ||||||
| 		File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion); | 		File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion); | ||||||
| 		if(!natives.exists()) { | 
 | ||||||
|  | 		if (!natives.exists()) { | ||||||
| 			natives.mkdirs(); | 			natives.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return natives; | 		return natives; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -167,6 +185,7 @@ public class LoomGradleExtension { | ||||||
| 			for (Dependency dependency : config.getDependencies()) { | 			for (Dependency dependency : config.getDependencies()) { | ||||||
| 				String group = dependency.getGroup(); | 				String group = dependency.getGroup(); | ||||||
| 				String name = dependency.getName(); | 				String name = dependency.getName(); | ||||||
|  | 
 | ||||||
| 				if (groupNameFilter.test(group, name)) { | 				if (groupNameFilter.test(group, name)) { | ||||||
| 					p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion()); | 					p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion()); | ||||||
| 					return dependency; | 					return dependency; | ||||||
|  | @ -181,12 +200,15 @@ public class LoomGradleExtension { | ||||||
| 	private <T> T recurseProjects(Function<Project, T> projectTFunction) { | 	private <T> T recurseProjects(Function<Project, T> projectTFunction) { | ||||||
| 		Project p = this.project; | 		Project p = this.project; | ||||||
| 		T result; | 		T result; | ||||||
|  | 
 | ||||||
| 		while (!AbstractPlugin.isRootProject(p)) { | 		while (!AbstractPlugin.isRootProject(p)) { | ||||||
| 			if ((result = projectTFunction.apply(p)) != null) { | 			if ((result = projectTFunction.apply(p)) != null) { | ||||||
| 				return result; | 				return result; | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			p = p.getRootProject(); | 			p = p.getRootProject(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		result = projectTFunction.apply(p); | 		result = projectTFunction.apply(p); | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  | @ -197,9 +219,11 @@ public class LoomGradleExtension { | ||||||
| 			List<Configuration> configs = new ArrayList<>(); | 			List<Configuration> configs = new ArrayList<>(); | ||||||
| 			// check compile classpath first | 			// check compile classpath first | ||||||
| 			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); | 			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); | ||||||
|  | 
 | ||||||
| 			if (possibleCompileClasspath != null) { | 			if (possibleCompileClasspath != null) { | ||||||
| 				configs.add(possibleCompileClasspath); | 				configs.add(possibleCompileClasspath); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			// failing that, buildscript | 			// failing that, buildscript | ||||||
| 			configs.addAll(p.getBuildscript().getConfigurations()); | 			configs.addAll(p.getBuildscript().getConfigurations()); | ||||||
| 
 | 
 | ||||||
|  | @ -242,15 +266,15 @@ public class LoomGradleExtension { | ||||||
| 		return dependencyManager; | 		return dependencyManager; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MinecraftProvider getMinecraftProvider(){ | 	public MinecraftProvider getMinecraftProvider() { | ||||||
| 		return getDependencyManager().getProvider(MinecraftProvider.class); | 		return getDependencyManager().getProvider(MinecraftProvider.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MinecraftMappedProvider getMinecraftMappedProvider(){ | 	public MinecraftMappedProvider getMinecraftMappedProvider() { | ||||||
| 		return getMappingsProvider().mappedProvider; | 		return getMappingsProvider().mappedProvider; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MappingsProvider getMappingsProvider(){ | 	public MappingsProvider getMappingsProvider() { | ||||||
| 		return getDependencyManager().getProvider(MappingsProvider.class); | 		return getDependencyManager().getProvider(MappingsProvider.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -259,7 +283,7 @@ public class LoomGradleExtension { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public String getRefmapName() { | 	public String getRefmapName() { | ||||||
| 		if(refmapName == null || refmapName.isEmpty()){ | 		if (refmapName == null || refmapName.isEmpty()) { | ||||||
| 			project.getLogger().warn("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json"); | 			project.getLogger().warn("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json"); | ||||||
| 			refmapName = project.getName() + "-refmap.json"; | 			refmapName = project.getName() + "-refmap.json"; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -24,26 +24,40 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom; | package net.fabricmc.loom; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftLibraryProvider; |  | ||||||
| import net.fabricmc.loom.task.*; |  | ||||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.Task; |  | ||||||
| import org.gradle.api.tasks.TaskContainer; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| 
 | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.Task; | ||||||
|  | import org.gradle.api.tasks.TaskContainer; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftLibraryProvider; | ||||||
|  | import net.fabricmc.loom.task.AbstractDecompileTask; | ||||||
|  | import net.fabricmc.loom.task.CleanLoomBinaries; | ||||||
|  | import net.fabricmc.loom.task.CleanLoomMappings; | ||||||
|  | import net.fabricmc.loom.task.DownloadAssetsTask; | ||||||
|  | import net.fabricmc.loom.task.GenEclipseRunsTask; | ||||||
|  | import net.fabricmc.loom.task.GenIdeaProjectTask; | ||||||
|  | import net.fabricmc.loom.task.GenVsCodeProjectTask; | ||||||
|  | import net.fabricmc.loom.task.MigrateMappingsTask; | ||||||
|  | import net.fabricmc.loom.task.RemapJarTask; | ||||||
|  | import net.fabricmc.loom.task.RemapLineNumbersTask; | ||||||
|  | import net.fabricmc.loom.task.RemapSourcesJarTask; | ||||||
|  | import net.fabricmc.loom.task.RunClientTask; | ||||||
|  | import net.fabricmc.loom.task.RunServerTask; | ||||||
|  | import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||||
|  | 
 | ||||||
| public class LoomGradlePlugin extends AbstractPlugin { | public class LoomGradlePlugin extends AbstractPlugin { | ||||||
| 	private static File getMappedByproduct(Project project, String suffix) { | 	private static File getMappedByproduct(Project project, String suffix) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||||
| 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||||
| 		String path = mappedJar.getAbsolutePath(); | 		String path = mappedJar.getAbsolutePath(); | ||||||
|  | 
 | ||||||
| 		if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) { | 		if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) { | ||||||
| 			throw new RuntimeException("Invalid mapped JAR path: " + path); | 			throw new RuntimeException("Invalid mapped JAR path: " + path); | ||||||
| 		} | 		} | ||||||
|  | @ -57,7 +71,6 @@ public class LoomGradlePlugin extends AbstractPlugin { | ||||||
| 
 | 
 | ||||||
| 		TaskContainer tasks = target.getTasks(); | 		TaskContainer tasks = target.getTasks(); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		tasks.register("cleanLoomBinaries", CleanLoomBinaries.class); | 		tasks.register("cleanLoomBinaries", CleanLoomBinaries.class); | ||||||
| 		tasks.register("cleanLoomMappings", CleanLoomMappings.class); | 		tasks.register("cleanLoomMappings", CleanLoomMappings.class); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,41 +24,42 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.util.StaticPathWatcher; |  | ||||||
| import net.fabricmc.mappings.Mappings; |  | ||||||
| import org.gradle.api.logging.Logging; |  | ||||||
| 
 |  | ||||||
| import java.io.FileInputStream; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.lang.ref.SoftReference; | import java.lang.ref.SoftReference; | ||||||
| import java.nio.file.*; | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.util.StaticPathWatcher; | ||||||
|  | import net.fabricmc.mappings.Mappings; | ||||||
|  | 
 | ||||||
| public final class MappingsCache { | public final class MappingsCache { | ||||||
|     public static final MappingsCache INSTANCE = new MappingsCache(); | 	public static final MappingsCache INSTANCE = new MappingsCache(); | ||||||
| 
 | 
 | ||||||
|     private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); | 	private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); | ||||||
| 
 | 
 | ||||||
|     public Mappings get(Path mappingsPath) { | 	public Mappings get(Path mappingsPath) { | ||||||
|         mappingsPath = mappingsPath.toAbsolutePath(); | 		mappingsPath = mappingsPath.toAbsolutePath(); | ||||||
|         if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { |  | ||||||
|             mappingsCache.remove(mappingsPath); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); | 		if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { | ||||||
|         if (ref != null && ref.get() != null) { | 			mappingsCache.remove(mappingsPath); | ||||||
|             return ref.get(); | 		} | ||||||
|         } else { | 
 | ||||||
|             try (InputStream stream = Files.newInputStream(mappingsPath)) { | 		SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); | ||||||
|                 Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | 
 | ||||||
|                 ref = new SoftReference<>(mappings); | 		if (ref != null && ref.get() != null) { | ||||||
|                 mappingsCache.put(mappingsPath, ref); | 			return ref.get(); | ||||||
|                 return mappings; | 		} else { | ||||||
|             } catch (IOException e) { | 			try (InputStream stream = Files.newInputStream(mappingsPath)) { | ||||||
|                 throw new RuntimeException(e); | 				Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||||
|             } | 				ref = new SoftReference<>(mappings); | ||||||
|         } | 				mappingsCache.put(mappingsPath, ref); | ||||||
|     } | 				return mappings; | ||||||
|  | 			} catch (IOException e) { | ||||||
|  | 				throw new RuntimeException(e); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,23 +24,22 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.nio.file.FileSystem; | ||||||
|  | import java.nio.file.FileSystems; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.DependencyProvider; | import net.fabricmc.loom.util.DependencyProvider; | ||||||
| import net.fabricmc.loom.util.Version; | import net.fabricmc.loom.util.Version; | ||||||
| import net.fabricmc.mappings.Mappings; | import net.fabricmc.mappings.Mappings; | ||||||
| import net.fabricmc.stitch.commands.CommandProposeFieldNames; | import net.fabricmc.stitch.commands.CommandProposeFieldNames; | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.FileInputStream; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.lang.ref.SoftReference; |  | ||||||
| import java.nio.file.FileSystem; |  | ||||||
| import java.nio.file.FileSystems; |  | ||||||
| import java.nio.file.Files; |  | ||||||
| import java.nio.file.Path; |  | ||||||
| import java.util.function.Consumer; |  | ||||||
| 
 | 
 | ||||||
| //TODO fix local mappings | //TODO fix local mappings | ||||||
| //TODO possibly use maven for mappings, can fix above at the same time | //TODO possibly use maven for mappings, can fix above at the same time | ||||||
|  | @ -84,6 +83,7 @@ public class MappingsProvider extends DependencyProvider { | ||||||
| 		if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) { | 		if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) { | ||||||
| 			if (!MAPPINGS_TINY_BASE.exists()) { | 			if (!MAPPINGS_TINY_BASE.exists()) { | ||||||
| 				project.getLogger().lifecycle(":extracting " + mappingsJar.getName()); | 				project.getLogger().lifecycle(":extracting " + mappingsJar.getName()); | ||||||
|  | 
 | ||||||
| 				try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) { | 				try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) { | ||||||
| 					Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny"); | 					Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny"); | ||||||
| 					Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath()); | 					Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath()); | ||||||
|  | @ -95,11 +95,7 @@ public class MappingsProvider extends DependencyProvider { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			project.getLogger().lifecycle(":populating field names"); | 			project.getLogger().lifecycle(":populating field names"); | ||||||
| 			new CommandProposeFieldNames().run(new String[] { | 			new CommandProposeFieldNames().run(new String[]{minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), MAPPINGS_TINY_BASE.getAbsolutePath(), MAPPINGS_TINY.getAbsolutePath()}); | ||||||
| 					minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), |  | ||||||
| 					MAPPINGS_TINY_BASE.getAbsolutePath(), |  | ||||||
| 					MAPPINGS_TINY.getAbsolutePath() |  | ||||||
| 			}); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		mappedProvider = new MinecraftMappedProvider(); | 		mappedProvider = new MinecraftMappedProvider(); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,16 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.FileReader; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.net.URL; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||||
|  | import org.gradle.api.GradleException; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.util.Checksum; | import net.fabricmc.loom.util.Checksum; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
|  | @ -34,15 +43,6 @@ import net.fabricmc.loom.util.assets.AssetIndex; | ||||||
| import net.fabricmc.loom.util.assets.AssetObject; | import net.fabricmc.loom.util.assets.AssetObject; | ||||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | import net.fabricmc.loom.util.progress.ProgressLogger; | ||||||
| 
 | 
 | ||||||
| import org.gradle.api.GradleException; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.FileReader; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.net.URL; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| public class MinecraftAssetsProvider { | public class MinecraftAssetsProvider { | ||||||
| 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | @ -53,13 +53,16 @@ public class MinecraftAssetsProvider { | ||||||
| 
 | 
 | ||||||
| 		// get existing cache files | 		// get existing cache files | ||||||
| 		File assets = new File(extension.getUserCache(), "assets"); | 		File assets = new File(extension.getUserCache(), "assets"); | ||||||
|  | 
 | ||||||
| 		if (!assets.exists()) { | 		if (!assets.exists()) { | ||||||
| 			assets.mkdirs(); | 			assets.mkdirs(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json"); | 		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json"); | ||||||
|  | 
 | ||||||
| 		if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { | 		if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { | ||||||
| 			project.getLogger().lifecycle(":downloading asset index"); | 			project.getLogger().lifecycle(":downloading asset index"); | ||||||
|  | 
 | ||||||
| 			if (offline) { | 			if (offline) { | ||||||
| 				if (assetsInfo.exists()) { | 				if (assetsInfo.exists()) { | ||||||
| 					//We know it's outdated but can't do anything about it, oh well | 					//We know it's outdated but can't do anything about it, oh well | ||||||
|  | @ -76,13 +79,16 @@ public class MinecraftAssetsProvider { | ||||||
| 		ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); | 		ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); | ||||||
| 		progressLogger.start("Downloading assets...", "assets"); | 		progressLogger.start("Downloading assets...", "assets"); | ||||||
| 		AssetIndex index; | 		AssetIndex index; | ||||||
|  | 
 | ||||||
| 		try (FileReader fileReader = new FileReader(assetsInfo)) { | 		try (FileReader fileReader = new FileReader(assetsInfo)) { | ||||||
| 			index = new Gson().fromJson(fileReader, AssetIndex.class); | 			index = new Gson().fromJson(fileReader, AssetIndex.class); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		Map<String, AssetObject> parent = index.getFileMap(); | 		Map<String, AssetObject> parent = index.getFileMap(); | ||||||
| 		final int totalSize = parent.size(); | 		final int totalSize = parent.size(); | ||||||
| 		int position = 0; | 		int position = 0; | ||||||
| 		project.getLogger().lifecycle(":downloading assets..."); | 		project.getLogger().lifecycle(":downloading assets..."); | ||||||
|  | 
 | ||||||
| 		for (Map.Entry<String, AssetObject> entry : parent.entrySet()) { | 		for (Map.Entry<String, AssetObject> entry : parent.entrySet()) { | ||||||
| 			AssetObject object = entry.getValue(); | 			AssetObject object = entry.getValue(); | ||||||
| 			String sha1 = object.getHash(); | 			String sha1 = object.getHash(); | ||||||
|  | @ -101,11 +107,14 @@ public class MinecraftAssetsProvider { | ||||||
| 					DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); | 					DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			String assetName = entry.getKey(); | 			String assetName = entry.getKey(); | ||||||
| 			int end = assetName.lastIndexOf("/") + 1; | 			int end = assetName.lastIndexOf("/") + 1; | ||||||
|  | 
 | ||||||
| 			if (end > 0) { | 			if (end > 0) { | ||||||
| 				assetName = assetName.substring(end); | 				assetName = assetName.substring(end); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded"); | 			progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded"); | ||||||
| 			position++; | 			position++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -24,27 +24,18 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.Gson; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.Checksum; |  | ||||||
| import net.fabricmc.loom.util.Constants; |  | ||||||
| import net.fabricmc.loom.util.DownloadUtil; |  | ||||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; |  | ||||||
| import net.fabricmc.loom.util.assets.AssetIndex; |  | ||||||
| import net.fabricmc.loom.util.assets.AssetObject; |  | ||||||
| import net.fabricmc.loom.util.progress.ProgressLogger; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileReader; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.net.URL; |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.Map; | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.Constants; | ||||||
|  | import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||||
| 
 | 
 | ||||||
| public class MinecraftLibraryProvider { | public class MinecraftLibraryProvider { | ||||||
| 
 |  | ||||||
| 	public File MINECRAFT_LIBS; | 	public File MINECRAFT_LIBS; | ||||||
| 
 | 
 | ||||||
| 	private Collection<File> libs = new HashSet<>(); | 	private Collection<File> libs = new HashSet<>(); | ||||||
|  | @ -61,6 +52,7 @@ public class MinecraftLibraryProvider { | ||||||
| 
 | 
 | ||||||
| 				// By default, they are all available on all sides | 				// By default, they are all available on all sides | ||||||
| 				/* boolean isClientOnly = false; | 				/* boolean isClientOnly = false; | ||||||
|  | 
 | ||||||
| 				if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) { | 				if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) { | ||||||
| 					isClientOnly = true; | 					isClientOnly = true; | ||||||
| 				} */ | 				} */ | ||||||
|  | @ -78,5 +70,4 @@ public class MinecraftLibraryProvider { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,73 +24,76 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.Constants; |  | ||||||
| import net.fabricmc.loom.util.DependencyProvider; |  | ||||||
| import net.fabricmc.loom.util.MapJarsTiny; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.Constants; | ||||||
|  | import net.fabricmc.loom.util.DependencyProvider; | ||||||
|  | import net.fabricmc.loom.util.MapJarsTiny; | ||||||
|  | 
 | ||||||
| public class MinecraftMappedProvider extends DependencyProvider { | public class MinecraftMappedProvider extends DependencyProvider { | ||||||
|     public File MINECRAFT_MAPPED_JAR; | 	public File MINECRAFT_MAPPED_JAR; | ||||||
|     public File MINECRAFT_INTERMEDIARY_JAR; | 	public File MINECRAFT_INTERMEDIARY_JAR; | ||||||
| 
 | 
 | ||||||
|     private MinecraftProvider minecraftProvider; | 	private MinecraftProvider minecraftProvider; | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||||
|         if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { | 		if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { | ||||||
|             throw new RuntimeException("mappings file not found"); | 			throw new RuntimeException("mappings file not found"); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         if (!extension.getMinecraftProvider().getMergedJar().exists()) { | 		if (!extension.getMinecraftProvider().getMergedJar().exists()) { | ||||||
|             throw new RuntimeException("input merged jar not found"); | 			throw new RuntimeException("input merged jar not found"); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         if(!getMappedJar().exists() || !getIntermediaryJar().exists()){ | 		if (!getMappedJar().exists() || !getIntermediaryJar().exists()) { | ||||||
|             if (getMappedJar().exists()) { | 			if (getMappedJar().exists()) { | ||||||
|                 getMappedJar().delete(); | 				getMappedJar().delete(); | ||||||
|             } | 			} | ||||||
|             if (getIntermediaryJar().exists()) { |  | ||||||
|                 getIntermediaryJar().delete(); |  | ||||||
|             } |  | ||||||
|             new MapJarsTiny().mapJars(minecraftProvider, this, project); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         if (!MINECRAFT_MAPPED_JAR.exists()) { | 			if (getIntermediaryJar().exists()) { | ||||||
|             throw new RuntimeException("mapped jar not found"); | 				getIntermediaryJar().delete(); | ||||||
|         } | 			} | ||||||
| 
 | 
 | ||||||
|         String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion; | 			new MapJarsTiny().mapJars(minecraftProvider, this, project); | ||||||
|         project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version)); | 		} | ||||||
|         version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName; |  | ||||||
|         project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version)); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | 		if (!MINECRAFT_MAPPED_JAR.exists()) { | ||||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 			throw new RuntimeException("mapped jar not found"); | ||||||
|         this.minecraftProvider = minecraftProvider; | 		} | ||||||
|         MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-"  + mappingsProvider.mappingsName + ".jar"); |  | ||||||
|         MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar"); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public Collection<File> getMapperPaths() { | 		String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion; | ||||||
|         return minecraftProvider.libraryProvider.getLibraries(); | 		project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||||
|     } | 		version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName; | ||||||
|  | 		project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     public File getIntermediaryJar() { | 	public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | ||||||
|         return MINECRAFT_INTERMEDIARY_JAR; | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|     } | 		this.minecraftProvider = minecraftProvider; | ||||||
|  | 		MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-" + mappingsProvider.mappingsName + ".jar"); | ||||||
|  | 		MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar"); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     public File getMappedJar() { | 	public Collection<File> getMapperPaths() { | ||||||
|         return MINECRAFT_MAPPED_JAR; | 		return minecraftProvider.libraryProvider.getLibraries(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	public File getIntermediaryJar() { | ||||||
|     public String getTargetConfig() { | 		return MINECRAFT_INTERMEDIARY_JAR; | ||||||
|         return Constants.MINECRAFT_NAMED; | 	} | ||||||
|     } | 
 | ||||||
|  | 	public File getMappedJar() { | ||||||
|  | 		return MINECRAFT_MAPPED_JAR; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getTargetConfig() { | ||||||
|  | 		return Constants.MINECRAFT_NAMED; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,18 +24,18 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.DownloadUtil; |  | ||||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| 
 | 
 | ||||||
| public class MinecraftNativesProvider { | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.DownloadUtil; | ||||||
|  | import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||||
|  | 
 | ||||||
|  | public class MinecraftNativesProvider { | ||||||
| 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo; | 		MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo; | ||||||
|  | @ -45,6 +45,7 @@ public class MinecraftNativesProvider { | ||||||
| 
 | 
 | ||||||
| 		for (MinecraftVersionInfo.Library library : versionInfo.libraries) { | 		for (MinecraftVersionInfo.Library library : versionInfo.libraries) { | ||||||
| 			File libJarFile = library.getFile(jarStore); | 			File libJarFile = library.getFile(jarStore); | ||||||
|  | 
 | ||||||
| 			if (library.allowed() && library.isNative() && libJarFile != null) { | 			if (library.allowed() && library.isNative() && libJarFile != null) { | ||||||
| 				DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger()); | 				DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger()); | ||||||
| 
 | 
 | ||||||
|  | @ -53,5 +54,4 @@ public class MinecraftNativesProvider { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,17 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
| import com.google.common.io.Files; |  | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.GsonBuilder; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.*; |  | ||||||
| import net.fabricmc.stitch.merge.JarMerger; |  | ||||||
| 
 |  | ||||||
| import org.gradle.api.GradleException; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.logging.Logger; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileReader; | import java.io.FileReader; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | @ -44,8 +33,24 @@ import java.util.Optional; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
| import java.util.zip.ZipError; | import java.util.zip.ZipError; | ||||||
| 
 | 
 | ||||||
| public class MinecraftProvider extends DependencyProvider { | import com.google.common.io.Files; | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.GsonBuilder; | ||||||
|  | import org.gradle.api.GradleException; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.logging.Logger; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.Checksum; | ||||||
|  | import net.fabricmc.loom.util.Constants; | ||||||
|  | import net.fabricmc.loom.util.DependencyProvider; | ||||||
|  | import net.fabricmc.loom.util.DownloadUtil; | ||||||
|  | import net.fabricmc.loom.util.ManifestVersion; | ||||||
|  | import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||||
|  | import net.fabricmc.loom.util.StaticPathWatcher; | ||||||
|  | import net.fabricmc.stitch.merge.JarMerger; | ||||||
|  | 
 | ||||||
|  | public class MinecraftProvider extends DependencyProvider { | ||||||
| 	public String minecraftVersion; | 	public String minecraftVersion; | ||||||
| 
 | 
 | ||||||
| 	public MinecraftVersionInfo versionInfo; | 	public MinecraftVersionInfo versionInfo; | ||||||
|  | @ -66,25 +71,26 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 		initFiles(project); | 		initFiles(project); | ||||||
| 
 | 
 | ||||||
| 		downloadMcJson(project, offline); | 		downloadMcJson(project, offline); | ||||||
|  | 
 | ||||||
| 		try (FileReader reader = new FileReader(MINECRAFT_JSON)) { | 		try (FileReader reader = new FileReader(MINECRAFT_JSON)) { | ||||||
| 			versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class); | 			versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Add Loom as an annotation processor | 		// Add Loom as an annotation processor | ||||||
|         addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly"); | 		addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly"); | ||||||
| 
 | 
 | ||||||
|         if (offline) { | 		if (offline) { | ||||||
|         	if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) { | 			if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) { | ||||||
|         		project.getLogger().debug("Found client and server jars, presuming up-to-date"); | 				project.getLogger().debug("Found client and server jars, presuming up-to-date"); | ||||||
|         	} else if (MINECRAFT_MERGED_JAR.exists()) { | 			} else if (MINECRAFT_MERGED_JAR.exists()) { | ||||||
|         		//Strictly we don't need the split jars if the merged one exists, let's try go on | 				//Strictly we don't need the split jars if the merged one exists, let's try go on | ||||||
|         		project.getLogger().warn("Missing game jar but merged jar present, things might end badly"); | 				project.getLogger().warn("Missing game jar but merged jar present, things might end badly"); | ||||||
|         	} else { | 			} else { | ||||||
|         		throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists()); | 				throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists()); | ||||||
|         	} | 			} | ||||||
|         } else { | 		} else { | ||||||
|         	downloadJars(project.getLogger()); | 			downloadJars(project.getLogger()); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
| 		libraryProvider = new MinecraftLibraryProvider(); | 		libraryProvider = new MinecraftLibraryProvider(); | ||||||
| 		libraryProvider.provide(this, project); | 		libraryProvider.provide(this, project); | ||||||
|  | @ -108,7 +114,6 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 		MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); | 		MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); | ||||||
| 		MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); | 		MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); | ||||||
| 		MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); | 		MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void downloadMcJson(Project project, boolean offline) throws IOException { | 	private void downloadMcJson(Project project, boolean offline) throws IOException { | ||||||
|  | @ -135,7 +140,7 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 		Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); | 		Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); | ||||||
| 
 | 
 | ||||||
| 		if(extension.customManifest != null){ | 		if (extension.customManifest != null) { | ||||||
| 			ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); | 			ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); | ||||||
| 			customVersion.id = minecraftVersion; | 			customVersion.id = minecraftVersion; | ||||||
| 			customVersion.url = extension.customManifest; | 			customVersion.url = extension.customManifest; | ||||||
|  | @ -143,7 +148,7 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 			project.getLogger().lifecycle("Using custom minecraft manifest"); | 			project.getLogger().lifecycle("Using custom minecraft manifest"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if(!optionalVersion.isPresent()){ | 		if (!optionalVersion.isPresent()) { | ||||||
| 			optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | 			optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -165,7 +170,6 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 		} else { | 		} else { | ||||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void downloadJars(Logger logger) throws IOException { | 	private void downloadJars(Logger logger) throws IOException { | ||||||
|  | @ -182,6 +186,7 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 	private void mergeJars(Logger logger) throws IOException { | 	private void mergeJars(Logger logger) throws IOException { | ||||||
| 		logger.lifecycle(":merging jars"); | 		logger.lifecycle(":merging jars"); | ||||||
|  | 
 | ||||||
| 		try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) { | 		try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) { | ||||||
| 			jarMerger.enableSyntheticParamsOffset(); | 			jarMerger.enableSyntheticParamsOffset(); | ||||||
| 			jarMerger.merge(); | 			jarMerger.merge(); | ||||||
|  |  | ||||||
|  | @ -24,29 +24,52 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | 
 | ||||||
| import org.gradle.api.file.FileCollection; | import org.gradle.api.file.FileCollection; | ||||||
| import org.gradle.api.tasks.Input; |  | ||||||
| import org.gradle.api.tasks.InputFile; | import org.gradle.api.tasks.InputFile; | ||||||
| import org.gradle.api.tasks.InputFiles; | import org.gradle.api.tasks.InputFiles; | ||||||
| import org.gradle.api.tasks.OutputFile; | import org.gradle.api.tasks.OutputFile; | ||||||
| 
 | 
 | ||||||
| import java.io.File; |  | ||||||
| 
 |  | ||||||
| public abstract class AbstractDecompileTask extends AbstractLoomTask { | public abstract class AbstractDecompileTask extends AbstractLoomTask { | ||||||
|     private Object input; | 	private Object input; | ||||||
|     private Object output; | 	private Object output; | ||||||
|     private Object lineMapFile; | 	private Object lineMapFile; | ||||||
|     private Object libraries; | 	private Object libraries; | ||||||
| 
 | 
 | ||||||
|     //@formatter:off | 	@InputFile | ||||||
|     @InputFile | 	public File getInput() { | ||||||
|     public File getInput() { return getProject().file(input); } | 		return getProject().file(input); | ||||||
|     @OutputFile public File getOutput() { return getProject().file(output); } | 	} | ||||||
|     @OutputFile public File getLineMapFile() { return getProject().file(lineMapFile); } | 
 | ||||||
|     @InputFiles public FileCollection getLibraries() { return getProject().files(libraries); } | 	@OutputFile | ||||||
|     public void setInput(Object input) { this.input = input; } | 	public File getOutput() { | ||||||
|     public void setOutput(Object output) { this.output = output; } | 		return getProject().file(output); | ||||||
|     public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } | 	} | ||||||
|     public void setLibraries(Object libraries) { this.libraries = libraries; } | 
 | ||||||
|     //@formatter:on | 	@OutputFile | ||||||
|  | 	public File getLineMapFile() { | ||||||
|  | 		return getProject().file(lineMapFile); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@InputFiles | ||||||
|  | 	public FileCollection getLibraries() { | ||||||
|  | 		return getProject().files(libraries); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setInput(Object input) { | ||||||
|  | 		this.input = input; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setOutput(Object output) { | ||||||
|  | 		this.output = output; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setLineMapFile(Object lineMapFile) { | ||||||
|  | 		this.lineMapFile = lineMapFile; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setLibraries(Object libraries) { | ||||||
|  | 		this.libraries = libraries; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,9 +27,7 @@ package net.fabricmc.loom.task; | ||||||
| import org.gradle.api.DefaultTask; | import org.gradle.api.DefaultTask; | ||||||
| 
 | 
 | ||||||
| public abstract class AbstractLoomTask extends DefaultTask { | public abstract class AbstractLoomTask extends DefaultTask { | ||||||
| 
 |  | ||||||
| 	public AbstractLoomTask() { | 	public AbstractLoomTask() { | ||||||
| 		setGroup("fabric"); | 		setGroup("fabric"); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,14 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; |  | ||||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; |  | ||||||
| import net.fabricmc.loom.util.OperatingSystem; |  | ||||||
| import net.fabricmc.loom.util.RunConfig; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.tasks.JavaExec; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
|  | @ -41,99 +33,113 @@ import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
| 
 | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.tasks.JavaExec; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
|  | import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||||
|  | import net.fabricmc.loom.util.RunConfig; | ||||||
|  | 
 | ||||||
| public abstract class AbstractRunTask extends JavaExec { | public abstract class AbstractRunTask extends JavaExec { | ||||||
|     private final Function<Project, RunConfig> configProvider; | 	private final Function<Project, RunConfig> configProvider; | ||||||
|     private RunConfig config; | 	private RunConfig config; | ||||||
| 
 | 
 | ||||||
|     public AbstractRunTask(Function<Project, RunConfig> config) { | 	public AbstractRunTask(Function<Project, RunConfig> config) { | ||||||
|         super(); | 		super(); | ||||||
|         setGroup("fabric"); | 		setGroup("fabric"); | ||||||
|         this.configProvider = config; | 		this.configProvider = config; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void exec() { | 	public void exec() { | ||||||
|         if (config == null) { | 		if (config == null) { | ||||||
|             config = configProvider.apply(getProject()); | 			config = configProvider.apply(getProject()); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||||
|         MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo; | 		MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo; | ||||||
|         MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
|         List<String> libs = new ArrayList<>(); | 		List<String> libs = new ArrayList<>(); | ||||||
|         for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) { |  | ||||||
|             libs.add(file.getAbsolutePath()); |  | ||||||
|         } |  | ||||||
|         for (Path file : extension.getUnmappedMods()) { |  | ||||||
|             if (Files.isRegularFile(file)) { |  | ||||||
|                 libs.add(file.toFile().getAbsolutePath()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         classpath(libs); | 		for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) { | ||||||
|         List<String> argsSplit = new ArrayList<>(); | 			libs.add(file.getAbsolutePath()); | ||||||
|         String[] args = config.programArgs.split(" "); | 		} | ||||||
|         int partPos = -1; |  | ||||||
|         for (int i = 0; i < args.length; i++) { |  | ||||||
|             if (partPos < 0) { |  | ||||||
|                 if (args[i].startsWith("\"")) { |  | ||||||
|                     if (args[i].endsWith("\"")) { |  | ||||||
|                         argsSplit.add(args[i].substring(1, args[i].length() - 1)); |  | ||||||
|                     } else { |  | ||||||
|                         partPos = i; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     argsSplit.add(args[i]); |  | ||||||
|                 } |  | ||||||
|             } else if (args[i].endsWith("\"")) { |  | ||||||
|                 StringBuilder builder = new StringBuilder(args[partPos].substring(1)); |  | ||||||
|                 for (int j = partPos + 1; j < i; j++) { |  | ||||||
|                     builder.append(" ").append(args[j]); |  | ||||||
|                 } |  | ||||||
|                 builder.append(" ").append(args[i], 0, args[i].length() - 1); |  | ||||||
|                 argsSplit.add(builder.toString()); |  | ||||||
|                 partPos = -1; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         args(argsSplit); | 		for (Path file : extension.getUnmappedMods()) { | ||||||
|         setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); | 			if (Files.isRegularFile(file)) { | ||||||
|  | 				libs.add(file.toFile().getAbsolutePath()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         super.exec(); | 		classpath(libs); | ||||||
|     } | 		List<String> argsSplit = new ArrayList<>(); | ||||||
|  | 		String[] args = config.programArgs.split(" "); | ||||||
|  | 		int partPos = -1; | ||||||
| 
 | 
 | ||||||
|     @Override | 		for (int i = 0; i < args.length; i++) { | ||||||
|     public void setWorkingDir(File dir) { | 			if (partPos < 0) { | ||||||
|         if (config == null) { | 				if (args[i].startsWith("\"")) { | ||||||
|             config = configProvider.apply(getProject()); | 					if (args[i].endsWith("\"")) { | ||||||
|         } | 						argsSplit.add(args[i].substring(1, args[i].length() - 1)); | ||||||
|  | 					} else { | ||||||
|  | 						partPos = i; | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					argsSplit.add(args[i]); | ||||||
|  | 				} | ||||||
|  | 			} else if (args[i].endsWith("\"")) { | ||||||
|  | 				StringBuilder builder = new StringBuilder(args[partPos].substring(1)); | ||||||
| 
 | 
 | ||||||
|         if(!dir.exists()){ | 				for (int j = partPos + 1; j < i; j++) { | ||||||
|             dir.mkdirs(); | 					builder.append(" ").append(args[j]); | ||||||
|         } | 				} | ||||||
|         super.setWorkingDir(dir); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 				builder.append(" ").append(args[i], 0, args[i].length() - 1); | ||||||
|     public String getMain() { | 				argsSplit.add(builder.toString()); | ||||||
|         if (config == null) { | 				partPos = -1; | ||||||
|             config = configProvider.apply(getProject()); | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         return config.mainClass; | 		args(argsSplit); | ||||||
|     } | 		setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); | ||||||
| 
 | 
 | ||||||
|     @Override | 		super.exec(); | ||||||
|     public List<String> getJvmArgs() { | 	} | ||||||
|         if (config == null) { | 
 | ||||||
|             config = configProvider.apply(getProject()); | 	@Override | ||||||
|         } | 	public void setWorkingDir(File dir) { | ||||||
|          | 		if (config == null) { | ||||||
|         LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | 			config = configProvider.apply(getProject()); | ||||||
|         List<String> superArgs = super.getJvmArgs(); | 		} | ||||||
|         List<String> args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList()); | 
 | ||||||
|         args.addAll(Arrays.asList(config.vmArgs.split(" "))); | 		if (!dir.exists()) { | ||||||
|         return args; | 			dir.mkdirs(); | ||||||
|     } | 		} | ||||||
|  | 
 | ||||||
|  | 		super.setWorkingDir(dir); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getMain() { | ||||||
|  | 		if (config == null) { | ||||||
|  | 			config = configProvider.apply(getProject()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return config.mainClass; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public List<String> getJvmArgs() { | ||||||
|  | 		if (config == null) { | ||||||
|  | 			config = configProvider.apply(getProject()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 		List<String> superArgs = super.getJvmArgs(); | ||||||
|  | 		List<String> args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList()); | ||||||
|  | 		args.addAll(Arrays.asList(config.vmArgs.split(" "))); | ||||||
|  | 		return args; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,26 +24,28 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.IOException; | ||||||
|  | 
 | ||||||
| import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| 
 | 
 | ||||||
| public class CleanLoomBinaries extends AbstractLoomTask { | public class CleanLoomBinaries extends AbstractLoomTask { | ||||||
|     @TaskAction | 	@TaskAction | ||||||
|     public void run() { | 	public void run() { | ||||||
|         Project project = this.getProject(); | 		Project project = this.getProject(); | ||||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|         extension.getMinecraftProvider().getMergedJar().delete(); | 		extension.getMinecraftProvider().getMergedJar().delete(); | ||||||
|         extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | 		extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||||
|         extension.getMinecraftMappedProvider().getMappedJar().delete(); | 		extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||||
| 	    try { | 
 | ||||||
| 		    FileUtils.deleteDirectory(extension.getNativesDirectory()); | 		try { | ||||||
| 		    FileUtils.deleteDirectory(extension.getNativesJarStore()); | 			FileUtils.deleteDirectory(extension.getNativesDirectory()); | ||||||
| 	    } catch (IOException e) { | 			FileUtils.deleteDirectory(extension.getNativesJarStore()); | ||||||
| 		    e.printStackTrace(); | 		} catch (IOException e) { | ||||||
| 	    } | 			e.printStackTrace(); | ||||||
|     } | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,27 +24,29 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.DeletingFileVisitor; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.tasks.TaskAction; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| 
 | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.tasks.TaskAction; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.DeletingFileVisitor; | ||||||
|  | 
 | ||||||
| public class CleanLoomMappings extends AbstractLoomTask { | public class CleanLoomMappings extends AbstractLoomTask { | ||||||
|     @TaskAction | 	@TaskAction | ||||||
|     public void run() { | 	public void run() { | ||||||
|         Project project = this.getProject(); | 		Project project = this.getProject(); | ||||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|         extension.getMappingsProvider().MAPPINGS_TINY.delete(); | 		extension.getMappingsProvider().MAPPINGS_TINY.delete(); | ||||||
|         extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete(); | 		extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete(); | ||||||
|         extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | 		extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||||
|         extension.getMinecraftMappedProvider().getMappedJar().delete(); | 		extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||||
|         try { | 
 | ||||||
|             Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); | 		try { | ||||||
|         } catch (IOException e) { | 			Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); | ||||||
|             throw new RuntimeException(e); | 		} catch (IOException e) { | ||||||
|         } | 			throw new RuntimeException(e); | ||||||
|     } | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,13 +24,14 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.IOException; | ||||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; | 
 | ||||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; |  | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||||
| 
 | 
 | ||||||
| public class DownloadAssetsTask extends AbstractLoomTask { | public class DownloadAssetsTask extends AbstractLoomTask { | ||||||
| 	@TaskAction | 	@TaskAction | ||||||
|  |  | ||||||
|  | @ -36,18 +36,18 @@ import org.gradle.process.JavaExecSpec; | ||||||
|  * Simple trait like interface for a Task that wishes to execute a java process |  * Simple trait like interface for a Task that wishes to execute a java process | ||||||
|  * with the classpath of the gradle plugin plus groovy. |  * with the classpath of the gradle plugin plus groovy. | ||||||
|  * |  * | ||||||
|  * Created by covers1624 on 11/02/19. |  * <p>Created by covers1624 on 11/02/19. | ||||||
|  */ |  */ | ||||||
| public interface ForkingJavaExecTask extends Task { | public interface ForkingJavaExecTask extends Task { | ||||||
|  | 	default ExecResult javaexec(Action<? super JavaExecSpec> action) { | ||||||
|  | 		ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations(); | ||||||
|  | 		DependencyHandler handler = getProject().getDependencies(); | ||||||
|  | 		FileCollection classpath = configurations.getByName("classpath")// | ||||||
|  | 				.plus(configurations.detachedConfiguration(handler.localGroovy())); | ||||||
| 
 | 
 | ||||||
|     default ExecResult javaexec(Action<? super JavaExecSpec> action) { | 		return getProject().javaexec(spec -> { | ||||||
|         ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations(); | 			spec.classpath(classpath); | ||||||
|         DependencyHandler handler = getProject().getDependencies(); | 			action.execute(spec); | ||||||
|         FileCollection classpath = configurations.getByName("classpath")// | 		}); | ||||||
|                 .plus(configurations.detachedConfiguration(handler.localGroovy())); | 	} | ||||||
|         return getProject().javaexec(spec -> { |  | ||||||
|             spec.classpath(classpath); |  | ||||||
|             action.execute(spec); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,33 +24,37 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.RunConfig; |  | ||||||
| import org.apache.commons.io.FileUtils; |  | ||||||
| import org.gradle.api.tasks.TaskAction; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| 
 | 
 | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
|  | import org.gradle.api.tasks.TaskAction; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.RunConfig; | ||||||
|  | 
 | ||||||
| public class GenEclipseRunsTask extends AbstractLoomTask { | public class GenEclipseRunsTask extends AbstractLoomTask { | ||||||
|  | 	@TaskAction | ||||||
|  | 	public void genRuns() throws IOException { | ||||||
|  | 		File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch"); | ||||||
|  | 		File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch"); | ||||||
| 
 | 
 | ||||||
|     @TaskAction | 		String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||||
|     public void genRuns() throws IOException { | 		String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||||
| 	    File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch"); |  | ||||||
| 	    File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch"); |  | ||||||
| 
 | 
 | ||||||
| 	    String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | 		if (!clientRunConfigs.exists()) { | ||||||
| 	    String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	    if(!clientRunConfigs.exists()) | 		if (!serverRunConfigs.exists()) { | ||||||
| 		    FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | ||||||
| 	    if(!serverRunConfigs.exists()) | 		} | ||||||
| 		    FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); |  | ||||||
| 
 | 
 | ||||||
| 	    File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir); | 		File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir); | ||||||
| 	    if(!runDir.exists()) |  | ||||||
| 		    runDir.mkdirs(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|  | 		if (!runDir.exists()) { | ||||||
|  | 			runDir.mkdirs(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,15 +24,8 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.AbstractPlugin; | import java.io.File; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.IOException; | ||||||
| import net.fabricmc.loom.util.RunConfig; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.tasks.TaskAction; |  | ||||||
| import org.w3c.dom.Document; |  | ||||||
| import org.w3c.dom.Element; |  | ||||||
| import org.w3c.dom.NodeList; |  | ||||||
| import org.xml.sax.SAXException; |  | ||||||
| 
 | 
 | ||||||
| import javax.xml.parsers.DocumentBuilder; | import javax.xml.parsers.DocumentBuilder; | ||||||
| import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||||
|  | @ -43,18 +36,28 @@ import javax.xml.transform.TransformerException; | ||||||
| import javax.xml.transform.TransformerFactory; | import javax.xml.transform.TransformerFactory; | ||||||
| import javax.xml.transform.dom.DOMSource; | import javax.xml.transform.dom.DOMSource; | ||||||
| import javax.xml.transform.stream.StreamResult; | import javax.xml.transform.stream.StreamResult; | ||||||
| import java.io.File; | 
 | ||||||
| import java.io.IOException; | import org.w3c.dom.Document; | ||||||
|  | import org.w3c.dom.Element; | ||||||
|  | import org.w3c.dom.NodeList; | ||||||
|  | import org.xml.sax.SAXException; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.tasks.TaskAction; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.AbstractPlugin; | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.RunConfig; | ||||||
| 
 | 
 | ||||||
| public class GenIdeaProjectTask extends AbstractLoomTask { | public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 
 |  | ||||||
| 	@TaskAction | 	@TaskAction | ||||||
| 	public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { | 	public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { | ||||||
| 		Project project = this.getProject(); | 		Project project = this.getProject(); | ||||||
|  | 
 | ||||||
| 		//Only generate the idea runs on the root project | 		//Only generate the idea runs on the root project | ||||||
| 		if(!AbstractPlugin.isRootProject(project)){ | 		if (!AbstractPlugin.isRootProject(project)) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		project.getLogger().lifecycle(":Building idea workspace"); | 		project.getLogger().lifecycle(":Building idea workspace"); | ||||||
| 
 | 
 | ||||||
|  | @ -65,8 +68,10 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 
 | 
 | ||||||
| 		NodeList list = doc.getElementsByTagName("component"); | 		NodeList list = doc.getElementsByTagName("component"); | ||||||
| 		Element runManager = null; | 		Element runManager = null; | ||||||
|  | 
 | ||||||
| 		for (int i = 0; i < list.getLength(); i++) { | 		for (int i = 0; i < list.getLength(); i++) { | ||||||
| 			Element element = (Element) list.item(i); | 			Element element = (Element) list.item(i); | ||||||
|  | 
 | ||||||
| 			if (element.getAttribute("name").equals("RunManager")) { | 			if (element.getAttribute("name").equals("RunManager")) { | ||||||
| 				runManager = element; | 				runManager = element; | ||||||
| 				break; | 				break; | ||||||
|  | @ -89,6 +94,7 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 		transformer.transform(source, result); | 		transformer.transform(source, result); | ||||||
| 
 | 
 | ||||||
| 		File runDir = new File(getProject().getRootDir(), extension.runDir); | 		File runDir = new File(getProject().getRootDir(), extension.runDir); | ||||||
|  | 
 | ||||||
| 		if (!runDir.exists()) { | 		if (!runDir.exists()) { | ||||||
| 			runDir.mkdirs(); | 			runDir.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -24,81 +24,85 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.GsonBuilder; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.util.RunConfig; |  | ||||||
| import org.apache.commons.io.FileUtils; |  | ||||||
| import org.gradle.api.tasks.TaskAction; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.GsonBuilder; | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
|  | import org.gradle.api.tasks.TaskAction; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.RunConfig; | ||||||
|  | 
 | ||||||
| //Recommended vscode plugins: | //Recommended vscode plugins: | ||||||
| // https://marketplace.visualstudio.com/items?itemName=redhat.java | // https://marketplace.visualstudio.com/items?itemName=redhat.java | ||||||
| // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug | // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug | ||||||
| // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack | // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack | ||||||
| public class GenVsCodeProjectTask extends AbstractLoomTask { | public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||||
|  | 	@TaskAction | ||||||
|  | 	public void genRuns() { | ||||||
|  | 		LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 		File projectDir = getProject().file(".vscode"); | ||||||
| 
 | 
 | ||||||
|     @TaskAction | 		if (!projectDir.exists()) { | ||||||
|     public void genRuns() { | 			projectDir.mkdir(); | ||||||
|         LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | 		} | ||||||
|         File projectDir = getProject().file(".vscode"); |  | ||||||
|         if (!projectDir.exists()) { |  | ||||||
|             projectDir.mkdir(); |  | ||||||
|         } |  | ||||||
|         File launchJson = new File(projectDir, "launch.json"); |  | ||||||
|         if (launchJson.exists()) { |  | ||||||
|             launchJson.delete(); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         VsCodeLaunch launch = new VsCodeLaunch(); | 		File launchJson = new File(projectDir, "launch.json"); | ||||||
|         launch.add(RunConfig.clientRunConfig(getProject())); |  | ||||||
|         launch.add(RunConfig.serverRunConfig(getProject())); |  | ||||||
| 
 | 
 | ||||||
|         Gson gson = new GsonBuilder().setPrettyPrinting().create(); | 		if (launchJson.exists()) { | ||||||
|         String json = gson.toJson(launch); | 			launchJson.delete(); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         try { | 		VsCodeLaunch launch = new VsCodeLaunch(); | ||||||
|             FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); | 		launch.add(RunConfig.clientRunConfig(getProject())); | ||||||
|         } catch (IOException e) { | 		launch.add(RunConfig.serverRunConfig(getProject())); | ||||||
|             throw new RuntimeException("Failed to write launch.json", e); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         File runDir = new File(getProject().getRootDir(), extension.runDir); | 		Gson gson = new GsonBuilder().setPrettyPrinting().create(); | ||||||
|         if (!runDir.exists()) { | 		String json = gson.toJson(launch); | ||||||
|             runDir.mkdirs(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static class VsCodeLaunch { | 		try { | ||||||
|         public String version = "0.2.0"; | 			FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); | ||||||
|         public List<VsCodeConfiguration> configurations = new ArrayList<>(); | 		} catch (IOException e) { | ||||||
|  | 			throw new RuntimeException("Failed to write launch.json", e); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         public void add(RunConfig runConfig) { | 		File runDir = new File(getProject().getRootDir(), extension.runDir); | ||||||
|             configurations.add(new VsCodeConfiguration(runConfig)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static class VsCodeConfiguration { | 		if (!runDir.exists()) { | ||||||
|         public String type = "java"; | 			runDir.mkdirs(); | ||||||
|         public String name; | 		} | ||||||
|         public String request = "launch"; | 	} | ||||||
|         public String cwd = "${workspaceFolder}/run"; |  | ||||||
|         public String console = "internalConsole"; |  | ||||||
|         public boolean stopOnEntry = false; |  | ||||||
|         public String mainClass; |  | ||||||
|         public String vmArgs; |  | ||||||
|         public String args; |  | ||||||
| 
 | 
 | ||||||
|         public VsCodeConfiguration(RunConfig runConfig) { | 	private static class VsCodeLaunch { | ||||||
|             this.name = runConfig.configName; | 		public String version = "0.2.0"; | ||||||
|             this.mainClass = runConfig.mainClass; | 		public List<VsCodeConfiguration> configurations = new ArrayList<>(); | ||||||
|             this.vmArgs = runConfig.vmArgs; | 
 | ||||||
|             this.args = runConfig.programArgs; | 		public void add(RunConfig runConfig) { | ||||||
|         } | 			configurations.add(new VsCodeConfiguration(runConfig)); | ||||||
|     } | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static class VsCodeConfiguration { | ||||||
|  | 		public String type = "java"; | ||||||
|  | 		public String name; | ||||||
|  | 		public String request = "launch"; | ||||||
|  | 		public String cwd = "${workspaceFolder}/run"; | ||||||
|  | 		public String console = "internalConsole"; | ||||||
|  | 		public boolean stopOnEntry = false; | ||||||
|  | 		public String mainClass; | ||||||
|  | 		public String vmArgs; | ||||||
|  | 		public String args; | ||||||
|  | 
 | ||||||
|  | 		VsCodeConfiguration(RunConfig runConfig) { | ||||||
|  | 			this.name = runConfig.configName; | ||||||
|  | 			this.mainClass = runConfig.mainClass; | ||||||
|  | 			this.vmArgs = runConfig.vmArgs; | ||||||
|  | 			this.args = runConfig.programArgs; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,10 +24,12 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.File; | ||||||
| import net.fabricmc.loom.util.Constants; | import java.io.FileInputStream; | ||||||
| import net.fabricmc.loom.util.Version; | import java.io.IOException; | ||||||
| import net.fabricmc.mappings.*; | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
| import org.cadixdev.lorenz.MappingSet; | import org.cadixdev.lorenz.MappingSet; | ||||||
| import org.cadixdev.lorenz.io.MappingsReader; | import org.cadixdev.lorenz.io.MappingsReader; | ||||||
| import org.cadixdev.mercury.Mercury; | import org.cadixdev.mercury.Mercury; | ||||||
|  | @ -35,149 +37,147 @@ import org.cadixdev.mercury.remapper.MercuryRemapper; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import java.io.FileInputStream; | import net.fabricmc.loom.util.Constants; | ||||||
| import java.io.IOException; | import net.fabricmc.loom.util.Version; | ||||||
| import java.util.HashMap; | import net.fabricmc.mappings.ClassEntry; | ||||||
| import java.util.Map; | import net.fabricmc.mappings.EntryTriple; | ||||||
|  | import net.fabricmc.mappings.FieldEntry; | ||||||
|  | import net.fabricmc.mappings.Mappings; | ||||||
|  | import net.fabricmc.mappings.MethodEntry; | ||||||
| 
 | 
 | ||||||
| public class MigrateMappingsTask extends AbstractLoomTask { | public class MigrateMappingsTask extends AbstractLoomTask { | ||||||
|     @TaskAction | 	@TaskAction | ||||||
|     public void doTask() throws Throwable { | 	public void doTask() throws Throwable { | ||||||
|         Project project = getProject(); | 		Project project = getProject(); | ||||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|         Map<String, ?> properties = project.getProperties(); | 		Map<String, ?> properties = project.getProperties(); | ||||||
| 
 | 
 | ||||||
|         project.getLogger().lifecycle(":loading mappings"); | 		project.getLogger().lifecycle(":loading mappings"); | ||||||
| 
 | 
 | ||||||
|         File mappingsFile = null; | 		File mappingsFile = null; | ||||||
| 
 | 
 | ||||||
|         if (properties.containsKey("targetMappingsFile")) { | 		if (properties.containsKey("targetMappingsFile")) { | ||||||
|             mappingsFile = new File((String) properties.get("targetMappingsFile")); | 			mappingsFile = new File((String) properties.get("targetMappingsFile")); | ||||||
|         } else if (properties.containsKey("targetMappingsArtifact")) { | 		} else if (properties.containsKey("targetMappingsArtifact")) { | ||||||
|             String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":"); | 			String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":"); | ||||||
|             if (artifactName.length != 3) { |  | ||||||
|                 throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact")); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             String mappingsName = artifactName[0] + "." + artifactName[1]; | 			if (artifactName.length != 3) { | ||||||
|  | 				throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact")); | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
|             Version v = new Version(artifactName[2]); | 			String mappingsName = artifactName[0] + "." + artifactName[1]; | ||||||
|             String minecraftVersion = v.getMinecraftVersion(); |  | ||||||
|             String mappingsVersion = v.getMappingsVersion(); |  | ||||||
| 
 | 
 | ||||||
|             mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion); | 			Version v = new Version(artifactName[2]); | ||||||
|         } | 			String minecraftVersion = v.getMinecraftVersion(); | ||||||
|  | 			String mappingsVersion = v.getMappingsVersion(); | ||||||
| 
 | 
 | ||||||
|         if (mappingsFile == null || !mappingsFile.exists()) { | 			mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion); | ||||||
|             throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null")); | 		} | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) { | 		if (mappingsFile == null || !mappingsFile.exists()) { | ||||||
|             throw new RuntimeException("Must specify input and output dir!"); | 			throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null")); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         File inputDir = new File((String) properties.get("inputDir")); | 		if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) { | ||||||
|         File outputDir = new File((String) properties.get("outputDir")); | 			throw new RuntimeException("Must specify input and output dir!"); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         if (!inputDir.exists() || !inputDir.isDirectory()) { | 		File inputDir = new File((String) properties.get("inputDir")); | ||||||
|             throw new RuntimeException("Could not find input directory: " + inputDir); | 		File outputDir = new File((String) properties.get("outputDir")); | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         if (!outputDir.exists()) { | 		if (!inputDir.exists() || !inputDir.isDirectory()) { | ||||||
|             if (!outputDir.mkdirs()) { | 			throw new RuntimeException("Could not find input directory: " + inputDir); | ||||||
|                 throw new RuntimeException("Could not create output directory:"  + outputDir); | 		} | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         Mappings sourceMappings = extension.getMappingsProvider().getMappings(); | 		if (!outputDir.exists()) { | ||||||
|         Mappings targetMappings; | 			if (!outputDir.mkdirs()) { | ||||||
|  | 				throw new RuntimeException("Could not create output directory:" + outputDir); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         try (FileInputStream stream = new FileInputStream(mappingsFile)) { | 		Mappings sourceMappings = extension.getMappingsProvider().getMappings(); | ||||||
|             targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | 		Mappings targetMappings; | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         project.getLogger().lifecycle(":joining mappings"); | 		try (FileInputStream stream = new FileInputStream(mappingsFile)) { | ||||||
|         MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read(); | 			targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         project.getLogger().lifecycle(":remapping"); | 		project.getLogger().lifecycle(":joining mappings"); | ||||||
|         Mercury mercury = new Mercury(); | 		MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read(); | ||||||
| 
 | 
 | ||||||
|         for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | 		project.getLogger().lifecycle(":remapping"); | ||||||
|             mercury.getClassPath().add(file.toPath()); | 		Mercury mercury = new Mercury(); | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | 		for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | ||||||
|             mercury.getClassPath().add(file.toPath()); | 			mercury.getClassPath().add(file.toPath()); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath()); | 		for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | ||||||
|         mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath()); | 			mercury.getClassPath().add(file.toPath()); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|         mercury.getProcessors().add(MercuryRemapper.create(mappingSet)); | 		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath()); | ||||||
|  | 		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath()); | ||||||
| 
 | 
 | ||||||
|         try { | 		mercury.getProcessors().add(MercuryRemapper.create(mappingSet)); | ||||||
|             mercury.rewrite(inputDir.toPath(), outputDir.toPath()); |  | ||||||
|         } catch (Exception e) { |  | ||||||
|             project.getLogger().warn("Could not remap fully!", e); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         project.getLogger().lifecycle(":cleaning file descriptors"); | 		try { | ||||||
|         System.gc(); | 			mercury.rewrite(inputDir.toPath(), outputDir.toPath()); | ||||||
|     } | 		} catch (Exception e) { | ||||||
|  | 			project.getLogger().warn("Could not remap fully!", e); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|     public static class MappingsJoiner extends MappingsReader { | 		project.getLogger().lifecycle(":cleaning file descriptors"); | ||||||
|         private final Mappings sourceMappings, targetMappings; | 		System.gc(); | ||||||
|         private final String fromNamespace, toNamespace; | 	} | ||||||
| 
 | 
 | ||||||
|         public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) { | 	public static class MappingsJoiner extends MappingsReader { | ||||||
|             this.sourceMappings = sourceMappings; | 		private final Mappings sourceMappings, targetMappings; | ||||||
|             this.targetMappings = targetMappings; | 		private final String fromNamespace, toNamespace; | ||||||
|             this.fromNamespace = fromNamespace; |  | ||||||
|             this.toNamespace = toNamespace; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         @Override | 		public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) { | ||||||
|         public MappingSet read(MappingSet mappings) throws IOException { | 			this.sourceMappings = sourceMappings; | ||||||
|             Map<String, ClassEntry> targetClasses = new HashMap<>(); | 			this.targetMappings = targetMappings; | ||||||
|             Map<EntryTriple, FieldEntry> targetFields = new HashMap<>(); | 			this.fromNamespace = fromNamespace; | ||||||
|             Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>(); | 			this.toNamespace = toNamespace; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|             targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c)); | 		@Override | ||||||
|             targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c)); | 		public MappingSet read(MappingSet mappings) throws IOException { | ||||||
|             targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c)); | 			Map<String, ClassEntry> targetClasses = new HashMap<>(); | ||||||
|  | 			Map<EntryTriple, FieldEntry> targetFields = new HashMap<>(); | ||||||
|  | 			Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>(); | ||||||
| 
 | 
 | ||||||
|             for (ClassEntry entry : sourceMappings.getClassEntries()) { | 			targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c)); | ||||||
|                 String from = entry.get(toNamespace); | 			targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c)); | ||||||
|                 String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | 			targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c)); | ||||||
| 
 | 
 | ||||||
|                 mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to); | 			for (ClassEntry entry : sourceMappings.getClassEntries()) { | ||||||
|             } | 				String from = entry.get(toNamespace); | ||||||
|  | 				String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||||
| 
 | 
 | ||||||
|             for (FieldEntry entry : sourceMappings.getFieldEntries()) { | 				mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to); | ||||||
|                 EntryTriple fromEntry = entry.get(toNamespace); | 			} | ||||||
|                 EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); |  | ||||||
| 
 | 
 | ||||||
|                 mappings.getOrCreateClassMapping(fromEntry.getOwner()) | 			for (FieldEntry entry : sourceMappings.getFieldEntries()) { | ||||||
|                         .getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()) | 				EntryTriple fromEntry = entry.get(toNamespace); | ||||||
|                         .setDeobfuscatedName(toEntry.getName()); | 				EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             for (MethodEntry entry : sourceMappings.getMethodEntries()) { | 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||||
|                 EntryTriple fromEntry = entry.get(toNamespace); | 			} | ||||||
|                 EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); |  | ||||||
| 
 | 
 | ||||||
|                 mappings.getOrCreateClassMapping(fromEntry.getOwner()) | 			for (MethodEntry entry : sourceMappings.getMethodEntries()) { | ||||||
|                         .getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()) | 				EntryTriple fromEntry = entry.get(toNamespace); | ||||||
|                         .setDeobfuscatedName(toEntry.getName()); | 				EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             return mappings; | 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||||
|         } | 			} | ||||||
| 
 | 
 | ||||||
|         @Override | 			return mappings; | ||||||
|         public void close() throws IOException { | 		} | ||||||
| 
 | 
 | ||||||
|         } | 		@Override | ||||||
|     } | 		public void close() throws IOException { } | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,6 +24,21 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.FileNotFoundException; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.util.LinkedHashSet; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.file.RegularFileProperty; | ||||||
|  | import org.gradle.api.provider.Property; | ||||||
|  | import org.gradle.api.tasks.Input; | ||||||
|  | import org.gradle.api.tasks.InputFile; | ||||||
|  | import org.gradle.api.tasks.TaskAction; | ||||||
|  | import org.gradle.jvm.tasks.Jar; | ||||||
|  | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
| import net.fabricmc.loom.util.GradleSupport; | import net.fabricmc.loom.util.GradleSupport; | ||||||
|  | @ -33,21 +48,6 @@ import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||||
| import net.fabricmc.tinyremapper.TinyRemapper; | import net.fabricmc.tinyremapper.TinyRemapper; | ||||||
| import net.fabricmc.tinyremapper.TinyUtils; | import net.fabricmc.tinyremapper.TinyUtils; | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.file.RegularFile; |  | ||||||
| import org.gradle.api.file.RegularFileProperty; |  | ||||||
| import org.gradle.api.provider.Property; |  | ||||||
| import org.gradle.api.tasks.Input; |  | ||||||
| import org.gradle.api.tasks.InputFile; |  | ||||||
| import org.gradle.api.tasks.TaskAction; |  | ||||||
| import org.gradle.jvm.tasks.Jar; |  | ||||||
| 
 |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.FileNotFoundException; |  | ||||||
| import java.nio.file.Files; |  | ||||||
| import java.nio.file.Path; |  | ||||||
| import java.util.LinkedHashSet; |  | ||||||
| import java.util.Set; |  | ||||||
| 
 | 
 | ||||||
| public class RemapJarTask extends Jar { | public class RemapJarTask extends Jar { | ||||||
| 	private RegularFileProperty input; | 	private RegularFileProperty input; | ||||||
|  | @ -86,6 +86,7 @@ public class RemapJarTask extends Jar { | ||||||
| 		TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper(); | 		TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper(); | ||||||
| 
 | 
 | ||||||
| 		remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)); | 		remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)); | ||||||
|  | 
 | ||||||
| 		if (mixinMapFile.exists()) { | 		if (mixinMapFile.exists()) { | ||||||
| 			remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM)); | 			remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM)); | ||||||
| 		} | 		} | ||||||
|  | @ -93,9 +94,11 @@ public class RemapJarTask extends Jar { | ||||||
| 		project.getLogger().lifecycle(":remapping " + input.getFileName()); | 		project.getLogger().lifecycle(":remapping " + input.getFileName()); | ||||||
| 
 | 
 | ||||||
| 		StringBuilder rc = new StringBuilder("Remap classpath: "); | 		StringBuilder rc = new StringBuilder("Remap classpath: "); | ||||||
|  | 
 | ||||||
| 		for (Path p : classpath) { | 		for (Path p : classpath) { | ||||||
| 			rc.append("\n - ").append(p.toString()); | 			rc.append("\n - ").append(p.toString()); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		project.getLogger().debug(rc.toString()); | 		project.getLogger().debug(rc.toString()); | ||||||
| 
 | 
 | ||||||
| 		TinyRemapper remapper = remapperBuilder.build(); | 		TinyRemapper remapper = remapperBuilder.build(); | ||||||
|  |  | ||||||
|  | @ -24,51 +24,68 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; | import java.io.File; | ||||||
| import net.fabricmc.loom.util.LineNumberRemapper; | import java.io.IOException; | ||||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | 
 | ||||||
| import net.fabricmc.stitch.util.StitchUtil; |  | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.tasks.Input; |  | ||||||
| import org.gradle.api.tasks.InputFile; | import org.gradle.api.tasks.InputFile; | ||||||
| import org.gradle.api.tasks.OutputFile; | import org.gradle.api.tasks.OutputFile; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||||
| import java.io.IOException; | import net.fabricmc.loom.util.LineNumberRemapper; | ||||||
|  | import net.fabricmc.loom.util.progress.ProgressLogger; | ||||||
|  | import net.fabricmc.stitch.util.StitchUtil; | ||||||
| 
 | 
 | ||||||
| public class RemapLineNumbersTask extends AbstractLoomTask { | public class RemapLineNumbersTask extends AbstractLoomTask { | ||||||
|     private Object input; | 	private Object input; | ||||||
|     private Object output; | 	private Object output; | ||||||
|     private Object lineMapFile; | 	private Object lineMapFile; | ||||||
| 
 | 
 | ||||||
|     @TaskAction | 	@TaskAction | ||||||
|     public void doTask() throws Throwable { | 	public void doTask() throws Throwable { | ||||||
|         Project project = getProject(); | 		Project project = getProject(); | ||||||
| 
 | 
 | ||||||
|         project.getLogger().lifecycle(":adjusting line numbers"); | 		project.getLogger().lifecycle(":adjusting line numbers"); | ||||||
|         LineNumberRemapper remapper = new LineNumberRemapper(); | 		LineNumberRemapper remapper = new LineNumberRemapper(); | ||||||
|         remapper.readMappings(getLineMapFile()); | 		remapper.readMappings(getLineMapFile()); | ||||||
| 
 | 
 | ||||||
|         ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName()); | 		ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName()); | ||||||
|         progressLogger.start("Adjusting line numbers", "linemap"); | 		progressLogger.start("Adjusting line numbers", "linemap"); | ||||||
| 
 | 
 | ||||||
|         try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); | 		try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) { | ||||||
|              StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) { | 			remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); | ||||||
|             remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); | 		} catch (IOException e) { | ||||||
|         } catch (IOException e) { | 			throw new RuntimeException(e); | ||||||
|             throw new RuntimeException(e); | 		} | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         progressLogger.completed(); | 		progressLogger.completed(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     //@formatter:off | 	@InputFile | ||||||
|     @InputFile public File getInput() { return getProject().file(input); } | 	public File getInput() { | ||||||
|     @InputFile public File getLineMapFile() { return getProject().file(lineMapFile); } | 		return getProject().file(input); | ||||||
|     @OutputFile public File getOutput() { return getProject().file(output); } | 	} | ||||||
|     public void setInput(Object input) { this.input = input; } | 
 | ||||||
|     public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } | 	@InputFile | ||||||
|     public void setOutput(Object output) { this.output = output; } | 	public File getLineMapFile() { | ||||||
|     //@formatter:on | 		return getProject().file(lineMapFile); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@OutputFile | ||||||
|  | 	public File getOutput() { | ||||||
|  | 		return getProject().file(output); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setInput(Object input) { | ||||||
|  | 		this.input = input; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setLineMapFile(Object lineMapFile) { | ||||||
|  | 		this.lineMapFile = lineMapFile; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setOutput(Object output) { | ||||||
|  | 		this.output = output; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,13 +24,14 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.util.SourceRemapper; | import java.io.File; | ||||||
|  | 
 | ||||||
| import org.gradle.api.tasks.Input; | import org.gradle.api.tasks.Input; | ||||||
| import org.gradle.api.tasks.InputFile; | import org.gradle.api.tasks.InputFile; | ||||||
| import org.gradle.api.tasks.OutputFile; | import org.gradle.api.tasks.OutputFile; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.util.SourceRemapper; | ||||||
| 
 | 
 | ||||||
| public class RemapSourcesJarTask extends AbstractLoomTask { | public class RemapSourcesJarTask extends AbstractLoomTask { | ||||||
| 	private Object input; | 	private Object input; | ||||||
|  | @ -42,13 +43,30 @@ public class RemapSourcesJarTask extends AbstractLoomTask { | ||||||
| 		SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); | 		SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//@formatter:off |  | ||||||
| 	@InputFile | 	@InputFile | ||||||
| 	public File getInput() { return getProject().file(input); } | 	public File getInput() { | ||||||
| 	@OutputFile public File getOutput() { return getProject().file(output == null ? input : output); } | 		return getProject().file(input); | ||||||
| 	@Input public String getTargetNamespace() { return direction; } | 	} | ||||||
| 	public void setInput(Object input) { this.input = input; } | 
 | ||||||
| 	public void setOutput(Object output) { this.output = output; } | 	@OutputFile | ||||||
| 	public void setTargetNamespace(String value) { this.direction = value; } | 	public File getOutput() { | ||||||
| 	//@formatter:on | 		return getProject().file(output == null ? input : output); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Input | ||||||
|  | 	public String getTargetNamespace() { | ||||||
|  | 		return direction; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setInput(Object input) { | ||||||
|  | 		this.input = input; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setOutput(Object output) { | ||||||
|  | 		this.output = output; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setTargetNamespace(String value) { | ||||||
|  | 		this.direction = value; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,123 +24,140 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task.fernflower; | package net.fabricmc.loom.task.fernflower; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.task.AbstractDecompileTask; | import static java.text.MessageFormat.format; | ||||||
| import net.fabricmc.loom.task.ForkingJavaExecTask; | 
 | ||||||
| import net.fabricmc.loom.util.ConsumingOutputStream; | import java.util.ArrayList; | ||||||
| import org.gradle.api.file.FileCollection; | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Stack; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  | 
 | ||||||
|  | import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; | ||||||
| import org.gradle.api.internal.project.ProjectInternal; | import org.gradle.api.internal.project.ProjectInternal; | ||||||
| import org.gradle.api.logging.LogLevel; | import org.gradle.api.logging.LogLevel; | ||||||
| import org.gradle.api.tasks.Input; | import org.gradle.api.tasks.Input; | ||||||
| import org.gradle.api.tasks.OutputFile; |  | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| import org.gradle.internal.logging.progress.ProgressLogger; | import org.gradle.internal.logging.progress.ProgressLogger; | ||||||
| import org.gradle.internal.logging.progress.ProgressLoggerFactory; | import org.gradle.internal.logging.progress.ProgressLoggerFactory; | ||||||
| import org.gradle.internal.service.ServiceRegistry; | import org.gradle.internal.service.ServiceRegistry; | ||||||
| import org.gradle.process.ExecResult; | import org.gradle.process.ExecResult; | ||||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; |  | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.task.AbstractDecompileTask; | ||||||
|  | import net.fabricmc.loom.task.ForkingJavaExecTask; | ||||||
|  | import net.fabricmc.loom.util.ConsumingOutputStream; | ||||||
| import net.fabricmc.loom.util.OperatingSystem; | import net.fabricmc.loom.util.OperatingSystem; | ||||||
| import java.util.*; |  | ||||||
| import java.util.function.Supplier; |  | ||||||
| 
 |  | ||||||
| import static java.text.MessageFormat.format; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Created by covers1624 on 9/02/19. |  * Created by covers1624 on 9/02/19. | ||||||
|  */ |  */ | ||||||
| public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask { | public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask { | ||||||
|  | 	private boolean noFork = false; | ||||||
|  | 	private int numThreads = Runtime.getRuntime().availableProcessors(); | ||||||
| 
 | 
 | ||||||
|     private boolean noFork = false; | 	@TaskAction | ||||||
|     private int numThreads = Runtime.getRuntime().availableProcessors(); | 	public void doTask() throws Throwable { | ||||||
|  | 		if (!OperatingSystem.is64Bit()) { | ||||||
|  | 			throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements"); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|     @TaskAction | 		Map<String, Object> options = new HashMap<>(); | ||||||
|     public void doTask() throws Throwable { | 		options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1"); | ||||||
|     	if(!OperatingSystem.is64Bit()){ | 		options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); | ||||||
|     		throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements"); | 		options.put(IFernflowerPreferences.LOG_LEVEL, "trace"); | ||||||
| 	    } | 		getLogging().captureStandardOutput(LogLevel.LIFECYCLE); | ||||||
| 
 | 
 | ||||||
|         Map<String, Object> options = new HashMap<>(); | 		List<String> args = new ArrayList<>(); | ||||||
|         options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1"); |  | ||||||
|         options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); |  | ||||||
|         options.put(IFernflowerPreferences.LOG_LEVEL, "trace"); |  | ||||||
|         getLogging().captureStandardOutput(LogLevel.LIFECYCLE); |  | ||||||
| 
 | 
 | ||||||
|         List<String> args = new ArrayList<>(); | 		options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); | ||||||
|  | 		args.add(getInput().getAbsolutePath()); | ||||||
|  | 		args.add("-o=" + getOutput().getAbsolutePath()); | ||||||
| 
 | 
 | ||||||
|         options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); | 		if (getLineMapFile() != null) { | ||||||
|         args.add(getInput().getAbsolutePath()); | 			args.add("-l=" + getLineMapFile().getAbsolutePath()); | ||||||
|         args.add("-o=" + getOutput().getAbsolutePath()); | 		} | ||||||
|         if (getLineMapFile() != null) { |  | ||||||
|             args.add("-l=" + getLineMapFile().getAbsolutePath()); |  | ||||||
|         } |  | ||||||
|         args.add("-t=" + getNumThreads()); |  | ||||||
| 
 | 
 | ||||||
|         //TODO, Decompiler breaks on jemalloc, J9 module-info.class? | 		args.add("-t=" + getNumThreads()); | ||||||
|         getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath())); |  | ||||||
| 
 | 
 | ||||||
|         ServiceRegistry registry = ((ProjectInternal) getProject()).getServices(); | 		//TODO, Decompiler breaks on jemalloc, J9 module-info.class? | ||||||
|         ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); | 		getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath())); | ||||||
|         ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile"); |  | ||||||
|         Supplier<ProgressLogger> loggerFactory = () -> { |  | ||||||
|             ProgressLogger pl = factory.newOperation(getClass(), progressGroup); |  | ||||||
|             pl.setDescription("decompile worker"); |  | ||||||
|             pl.started(); |  | ||||||
|             return pl; |  | ||||||
|         }; |  | ||||||
|         Stack<ProgressLogger> freeLoggers = new Stack<>(); |  | ||||||
|         Map<String, ProgressLogger> inUseLoggers = new HashMap<>(); |  | ||||||
| 
 | 
 | ||||||
|         progressGroup.started(); | 		ServiceRegistry registry = ((ProjectInternal) getProject()).getServices(); | ||||||
|         ExecResult result = javaexec(spec -> { | 		ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); | ||||||
|             spec.setMain(ForkedFFExecutor.class.getName()); | 		ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile"); | ||||||
|             spec.jvmArgs("-Xms200m", "-Xmx3G"); | 		Supplier<ProgressLogger> loggerFactory = () -> { | ||||||
|             spec.setArgs(args); | 			ProgressLogger pl = factory.newOperation(getClass(), progressGroup); | ||||||
|             spec.setErrorOutput(System.err); | 			pl.setDescription("decompile worker"); | ||||||
|             spec.setStandardOutput(new ConsumingOutputStream(line -> { | 			pl.started(); | ||||||
|                 if (line.startsWith("Listening for transport") || !line.contains("::")) { | 			return pl; | ||||||
|                     System.out.println(line); | 		}; | ||||||
|                     return; | 		Stack<ProgressLogger> freeLoggers = new Stack<>(); | ||||||
|                 } | 		Map<String, ProgressLogger> inUseLoggers = new HashMap<>(); | ||||||
| 
 | 
 | ||||||
|                 int sepIdx = line.indexOf("::"); | 		progressGroup.started(); | ||||||
|                 String id = line.substring(0, sepIdx).trim(); | 		ExecResult result = javaexec(spec -> { | ||||||
|                 String data = line.substring(sepIdx + 2).trim(); | 			spec.setMain(ForkedFFExecutor.class.getName()); | ||||||
|  | 			spec.jvmArgs("-Xms200m", "-Xmx3G"); | ||||||
|  | 			spec.setArgs(args); | ||||||
|  | 			spec.setErrorOutput(System.err); | ||||||
|  | 			spec.setStandardOutput(new ConsumingOutputStream(line -> { | ||||||
|  | 				if (line.startsWith("Listening for transport") || !line.contains("::")) { | ||||||
|  | 					System.out.println(line); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
|                 ProgressLogger logger = inUseLoggers.get(id); | 				int sepIdx = line.indexOf("::"); | ||||||
|  | 				String id = line.substring(0, sepIdx).trim(); | ||||||
|  | 				String data = line.substring(sepIdx + 2).trim(); | ||||||
| 
 | 
 | ||||||
|                 String[] segs = data.split(" "); | 				ProgressLogger logger = inUseLoggers.get(id); | ||||||
|                 if (segs[0].equals("waiting")) { |  | ||||||
|                     if (logger != null) { |  | ||||||
|                         logger.progress("Idle.."); |  | ||||||
|                         inUseLoggers.remove(id); |  | ||||||
|                         freeLoggers.push(logger); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if (logger == null) { |  | ||||||
|                         if (!freeLoggers.isEmpty()) { |  | ||||||
|                             logger = freeLoggers.pop(); |  | ||||||
|                         } else { |  | ||||||
|                             logger = loggerFactory.get(); |  | ||||||
|                         } |  | ||||||
|                         inUseLoggers.put(id, logger); |  | ||||||
|                     } |  | ||||||
|                     logger.progress(data); |  | ||||||
|                 } |  | ||||||
|             })); |  | ||||||
|         }); |  | ||||||
|         inUseLoggers.values().forEach(ProgressLogger::completed); |  | ||||||
|         freeLoggers.forEach(ProgressLogger::completed); |  | ||||||
|         progressGroup.completed(); |  | ||||||
| 
 | 
 | ||||||
|         result.rethrowFailure(); | 				String[] segs = data.split(" "); | ||||||
|         result.assertNormalExitValue(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     //@formatter:off | 				if (segs[0].equals("waiting")) { | ||||||
|     @Input public int getNumThreads() { return numThreads; } | 					if (logger != null) { | ||||||
|     @Input public boolean isNoFork() { return noFork; } | 						logger.progress("Idle.."); | ||||||
|     public void setNoFork(boolean noFork) { this.noFork = noFork; } | 						inUseLoggers.remove(id); | ||||||
|     public void setNumThreads(int numThreads) { this.numThreads = numThreads; } | 						freeLoggers.push(logger); | ||||||
|     //@formatter:on | 					} | ||||||
|  | 				} else { | ||||||
|  | 					if (logger == null) { | ||||||
|  | 						if (!freeLoggers.isEmpty()) { | ||||||
|  | 							logger = freeLoggers.pop(); | ||||||
|  | 						} else { | ||||||
|  | 							logger = loggerFactory.get(); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						inUseLoggers.put(id, logger); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					logger.progress(data); | ||||||
|  | 				} | ||||||
|  | 			})); | ||||||
|  | 		}); | ||||||
|  | 		inUseLoggers.values().forEach(ProgressLogger::completed); | ||||||
|  | 		freeLoggers.forEach(ProgressLogger::completed); | ||||||
|  | 		progressGroup.completed(); | ||||||
|  | 
 | ||||||
|  | 		result.rethrowFailure(); | ||||||
|  | 		result.assertNormalExitValue(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Input | ||||||
|  | 	public int getNumThreads() { | ||||||
|  | 		return numThreads; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Input | ||||||
|  | 	public boolean isNoFork() { | ||||||
|  | 		return noFork; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setNoFork(boolean noFork) { | ||||||
|  | 		this.noFork = noFork; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setNumThreads(int numThreads) { | ||||||
|  | 		this.numThreads = numThreads; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,26 +24,29 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task.fernflower; | package net.fabricmc.loom.task.fernflower; | ||||||
| 
 | 
 | ||||||
| import org.jetbrains.java.decompiler.util.InterpreterUtil; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||||
| import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||||
| 
 | 
 | ||||||
|  | import org.jetbrains.java.decompiler.util.InterpreterUtil; | ||||||
|  | 
 | ||||||
| public class FernFlowerUtils { | public class FernFlowerUtils { | ||||||
| 	public static byte[] getBytecode(String externalPath, String internalPath) throws IOException { | 	public static byte[] getBytecode(String externalPath, String internalPath) throws IOException { | ||||||
| 	    File file = new File(externalPath); | 		File file = new File(externalPath); | ||||||
| 	    if (internalPath == null) { | 
 | ||||||
| 	        return InterpreterUtil.getBytes(file); | 		if (internalPath == null) { | ||||||
| 	    } else { | 			return InterpreterUtil.getBytes(file); | ||||||
| 	        try (ZipFile archive = new ZipFile(file)) { | 		} else { | ||||||
| 	            ZipEntry entry = archive.getEntry(internalPath); | 			try (ZipFile archive = new ZipFile(file)) { | ||||||
| 	            if (entry == null) { | 				ZipEntry entry = archive.getEntry(internalPath); | ||||||
| 	                throw new IOException("Entry not found: " + internalPath); | 
 | ||||||
| 	            } | 				if (entry == null) { | ||||||
| 	            return InterpreterUtil.getBytes(archive, entry); | 					throw new IOException("Entry not found: " + internalPath); | ||||||
| 	        } | 				} | ||||||
| 	    } | 
 | ||||||
|  | 				return InterpreterUtil.getBytes(archive, entry); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,82 +24,92 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task.fernflower; | package net.fabricmc.loom.task.fernflower; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Objects; | ||||||
|  | 
 | ||||||
| import org.jetbrains.java.decompiler.main.Fernflower; | import org.jetbrains.java.decompiler.main.Fernflower; | ||||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||||
| import org.jetbrains.java.decompiler.main.extern.IResultSaver; | import org.jetbrains.java.decompiler.main.extern.IResultSaver; | ||||||
| 
 | 
 | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.*; |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Entry point for Forked FernFlower task. |  * Entry point for Forked FernFlower task. | ||||||
|  * Takes one parameter, a single file, each line is treated as command line input. |  * Takes one parameter, a single file, each line is treated as command line input. | ||||||
|  * Forces one input file. |  * Forces one input file. | ||||||
|  * Forces one output file using '-o=/path/to/output' |  * Forces one output file using '-o=/path/to/output' | ||||||
|  * |  | ||||||
|  * Created by covers1624 on 11/02/19. |  * Created by covers1624 on 11/02/19. | ||||||
|  */ |  */ | ||||||
| public class ForkedFFExecutor { | public class ForkedFFExecutor { | ||||||
|  | 	public static void main(String[] args) throws IOException { | ||||||
|  | 		Map<String, Object> options = new HashMap<>(); | ||||||
|  | 		File input = null; | ||||||
|  | 		File output = null; | ||||||
|  | 		File lineMap = null; | ||||||
|  | 		List<File> libraries = new ArrayList<>(); | ||||||
|  | 		int numThreads = 0; | ||||||
| 
 | 
 | ||||||
|     public static void main(String[] args) throws IOException { | 		boolean isOption = true; | ||||||
|         Map<String, Object> options = new HashMap<>(); |  | ||||||
|         File input = null; |  | ||||||
|         File output = null; |  | ||||||
|         File lineMap = null; |  | ||||||
|         List<File> libraries = new ArrayList<>(); |  | ||||||
|         int numThreads = 0; |  | ||||||
| 
 | 
 | ||||||
|         boolean isOption = true; | 		for (String arg : args) { | ||||||
|         for (String arg : args) { | 			if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { | ||||||
|             if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { | 				String value = arg.substring(5); | ||||||
|                 String value = arg.substring(5); |  | ||||||
|                 if ("true".equalsIgnoreCase(value)) { |  | ||||||
|                     value = "1"; |  | ||||||
|                 } else if ("false".equalsIgnoreCase(value)) { |  | ||||||
|                     value = "0"; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 options.put(arg.substring(1, 4), value); | 				if ("true".equalsIgnoreCase(value)) { | ||||||
|             } else { | 					value = "1"; | ||||||
|                 isOption = false; | 				} else if ("false".equalsIgnoreCase(value)) { | ||||||
|                 if (arg.startsWith("-e=")) { | 					value = "0"; | ||||||
|                     libraries.add(new File(arg.substring(3))); | 				} | ||||||
|                 } else if (arg.startsWith("-o=")) { |  | ||||||
|                     if (output != null) { |  | ||||||
|                         throw new RuntimeException("Unable to set more than one output."); |  | ||||||
|                     } |  | ||||||
|                     output = new File(arg.substring(3)); |  | ||||||
|                 } else if (arg.startsWith("-l=")) { |  | ||||||
|                     if (lineMap != null) { |  | ||||||
|                         throw new RuntimeException("Unable to set more than one lineMap file."); |  | ||||||
|                     } |  | ||||||
|                     lineMap = new File(arg.substring(3)); |  | ||||||
|                 } else if (arg.startsWith("-t=")) { |  | ||||||
|                     numThreads = Integer.parseInt(arg.substring(3)); |  | ||||||
|                 } else { |  | ||||||
|                     if (input != null) { |  | ||||||
|                         throw new RuntimeException("Unable to set more than one input."); |  | ||||||
|                     } |  | ||||||
|                     input = new File(arg); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         Objects.requireNonNull(input, "Input not set."); | 				options.put(arg.substring(1, 4), value); | ||||||
|         Objects.requireNonNull(output, "Output not set."); | 			} else { | ||||||
|  | 				isOption = false; | ||||||
| 
 | 
 | ||||||
|         runFF(options, libraries, input, output, lineMap); | 				if (arg.startsWith("-e=")) { | ||||||
|     } | 					libraries.add(new File(arg.substring(3))); | ||||||
|  | 				} else if (arg.startsWith("-o=")) { | ||||||
|  | 					if (output != null) { | ||||||
|  | 						throw new RuntimeException("Unable to set more than one output."); | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
|     public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) { | 					output = new File(arg.substring(3)); | ||||||
|         IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); | 				} else if (arg.startsWith("-l=")) { | ||||||
|         IFernflowerLogger logger = new ThreadIDFFLogger(); | 					if (lineMap != null) { | ||||||
|         Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); | 						throw new RuntimeException("Unable to set more than one lineMap file."); | ||||||
|         for (File library : libraries) { | 					} | ||||||
|             ff.addLibrary(library); | 
 | ||||||
|         } | 					lineMap = new File(arg.substring(3)); | ||||||
|         ff.addSource(input); | 				} else if (arg.startsWith("-t=")) { | ||||||
|         ff.decompileContext(); | 					numThreads = Integer.parseInt(arg.substring(3)); | ||||||
|     } | 				} else { | ||||||
|  | 					if (input != null) { | ||||||
|  | 						throw new RuntimeException("Unable to set more than one input."); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					input = new File(arg); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Objects.requireNonNull(input, "Input not set."); | ||||||
|  | 		Objects.requireNonNull(output, "Output not set."); | ||||||
|  | 
 | ||||||
|  | 		runFF(options, libraries, input, output, lineMap); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) { | ||||||
|  | 		IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); | ||||||
|  | 		IFernflowerLogger logger = new ThreadIDFFLogger(); | ||||||
|  | 		Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); | ||||||
|  | 
 | ||||||
|  | 		for (File library : libraries) { | ||||||
|  | 			ff.addLibrary(library); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ff.addSource(input); | ||||||
|  | 		ff.decompileContext(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,14 +31,9 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||||
|  * Created by covers1624 on 11/02/19. |  * Created by covers1624 on 11/02/19. | ||||||
|  */ |  */ | ||||||
| public class NoopFFLogger extends IFernflowerLogger { | public class NoopFFLogger extends IFernflowerLogger { | ||||||
|  | 	@Override | ||||||
|  | 	public void writeMessage(String message, Severity severity) { } | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void writeMessage(String message, Severity severity) { | 	public void writeMessage(String message, Severity severity, Throwable t) { } | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void writeMessage(String message, Severity severity, Throwable t) { |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,108 +24,108 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task.fernflower; | package net.fabricmc.loom.task.fernflower; | ||||||
| 
 | 
 | ||||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; |  | ||||||
| 
 |  | ||||||
| import java.io.PrintStream; | import java.io.PrintStream; | ||||||
| import java.text.MessageFormat; | import java.text.MessageFormat; | ||||||
| import java.util.Stack; | import java.util.Stack; | ||||||
| 
 | 
 | ||||||
|  | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * This logger simply prints what each thread is doing |  * This logger simply prints what each thread is doing | ||||||
|  * to the console in a machine parsable way. |  * to the console in a machine parsable way. | ||||||
|  * |  * | ||||||
|  * Created by covers1624 on 11/02/19. |  * <p>Created by covers1624 on 11/02/19. | ||||||
|  */ |  */ | ||||||
| public class ThreadIDFFLogger extends IFernflowerLogger { | public class ThreadIDFFLogger extends IFernflowerLogger { | ||||||
|  | 	public final PrintStream stdOut; | ||||||
|  | 	public final PrintStream stdErr; | ||||||
| 
 | 
 | ||||||
|     public final PrintStream stdOut; | 	private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); | ||||||
|     public final PrintStream stdErr; | 	private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); | ||||||
| 
 | 
 | ||||||
|     private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); | 	public ThreadIDFFLogger() { | ||||||
|     private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); | 		this(System.err, System.out); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     public ThreadIDFFLogger() { | 	public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { | ||||||
|         this(System.err, System.out); | 		this.stdOut = stdOut; | ||||||
|     } | 		this.stdErr = stdErr; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { | 	@Override | ||||||
|         this.stdOut = stdOut; | 	public void writeMessage(String message, Severity severity) { | ||||||
|         this.stdErr = stdErr; | 		System.err.println(message); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void writeMessage(String message, Severity severity) { | 	public void writeMessage(String message, Severity severity, Throwable t) { | ||||||
|         System.err.println(message); | 		System.err.println(message); | ||||||
|     } | 		t.printStackTrace(System.err); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	private void print() { | ||||||
|     public void writeMessage(String message, Severity severity, Throwable t) { | 		Thread thread = Thread.currentThread(); | ||||||
|         System.err.println(message); | 		long id = thread.getId(); | ||||||
|         t.printStackTrace(System.err); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private void print() { | 		if (line.get().isEmpty()) { | ||||||
|         Thread thread = Thread.currentThread(); | 			System.out.println(MessageFormat.format("{0} :: waiting", id)); | ||||||
|         long id = thread.getId(); | 			return; | ||||||
|         if (line.get().isEmpty()) { | 		} | ||||||
|             System.out.println(MessageFormat.format("{0} :: waiting", id)); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         String line = this.line.get().peek(); |  | ||||||
|         System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim()); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 		String line = this.line.get().peek(); | ||||||
|     public void startReadingClass(String className) { | 		System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim()); | ||||||
|         workingClass.get().push(className); | 	} | ||||||
|         line.get().push("Decompiling " + className); |  | ||||||
|         print(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void startClass(String className) { | 	public void startReadingClass(String className) { | ||||||
|         workingClass.get().push(className); | 		workingClass.get().push(className); | ||||||
|         line.get().push("Decompiling " + className); | 		line.get().push("Decompiling " + className); | ||||||
|         print(); | 		print(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void startMethod(String methodName) { | 	public void startClass(String className) { | ||||||
|         String className = workingClass.get().peek(); | 		workingClass.get().push(className); | ||||||
|         line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" "))); | 		line.get().push("Decompiling " + className); | ||||||
|         print(); | 		print(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void endMethod() { | 	public void startMethod(String methodName) { | ||||||
|         line.get().pop(); | 		String className = workingClass.get().peek(); | ||||||
|         print(); | 		line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" "))); | ||||||
|     } | 		print(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void endClass() { | 	public void endMethod() { | ||||||
|         line.get().pop(); | 		line.get().pop(); | ||||||
|         workingClass.get().pop(); | 		print(); | ||||||
|         print(); | 	} | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void startWriteClass(String className) { | 	public void endClass() { | ||||||
|         line.get().push("Writing " + className); | 		line.get().pop(); | ||||||
|         print(); | 		workingClass.get().pop(); | ||||||
|     } | 		print(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void endWriteClass() { | 	public void startWriteClass(String className) { | ||||||
|         line.get().pop(); | 		line.get().push("Writing " + className); | ||||||
|         print(); | 		print(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void endReadingClass() { | 	public void endWriteClass() { | ||||||
|         line.get().pop(); | 		line.get().pop(); | ||||||
|         workingClass.get().pop(); | 		print(); | ||||||
|         print(); | 	} | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void endReadingClass() { | ||||||
|  | 		line.get().pop(); | ||||||
|  | 		workingClass.get().pop(); | ||||||
|  | 		print(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task.fernflower; | package net.fabricmc.loom.task.fernflower; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.fernflower.api.IFabricResultSaver; | import java.io.File; | ||||||
| import org.jetbrains.java.decompiler.main.DecompilerContext; | import java.io.FileOutputStream; | ||||||
| import org.jetbrains.java.decompiler.main.extern.IResultSaver; | import java.io.FileWriter; | ||||||
| 
 | import java.io.IOException; | ||||||
| import java.io.*; | import java.io.PrintWriter; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | @ -42,108 +42,136 @@ import java.util.jar.Manifest; | ||||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||||
| import java.util.zip.ZipOutputStream; | import java.util.zip.ZipOutputStream; | ||||||
| 
 | 
 | ||||||
|  | import org.jetbrains.java.decompiler.main.DecompilerContext; | ||||||
|  | import org.jetbrains.java.decompiler.main.extern.IResultSaver; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.fernflower.api.IFabricResultSaver; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Created by covers1624 on 18/02/19. |  * Created by covers1624 on 18/02/19. | ||||||
|  */ |  */ | ||||||
| public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver { | public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver { | ||||||
|     private final Supplier<File> output; | 	private final Supplier<File> output; | ||||||
|     private final Supplier<File> lineMapFile; | 	private final Supplier<File> lineMapFile; | ||||||
| 
 | 
 | ||||||
|     public Map<String, ZipOutputStream> outputStreams = new HashMap<>(); | 	public Map<String, ZipOutputStream> outputStreams = new HashMap<>(); | ||||||
|     public Map<String, ExecutorService> saveExecutors = new HashMap<>(); | 	public Map<String, ExecutorService> saveExecutors = new HashMap<>(); | ||||||
|     public PrintWriter lineMapWriter; | 	public PrintWriter lineMapWriter; | ||||||
| 
 | 
 | ||||||
|     public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) { | 	public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) { | ||||||
|         this.output = output; | 		this.output = output; | ||||||
|         this.lineMapFile = lineMapFile; | 		this.lineMapFile = lineMapFile; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void createArchive(String path, String archiveName, Manifest manifest) { | 	public void createArchive(String path, String archiveName, Manifest manifest) { | ||||||
|         String key = path + "/" + archiveName; | 		String key = path + "/" + archiveName; | ||||||
|         File file = output.get(); | 		File file = output.get(); | ||||||
|         try { |  | ||||||
|             FileOutputStream fos = new FileOutputStream(file); |  | ||||||
|             ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest); |  | ||||||
|             outputStreams.put(key, zos); |  | ||||||
|             saveExecutors.put(key, Executors.newSingleThreadExecutor()); |  | ||||||
|         } catch (IOException e) { |  | ||||||
|             throw new RuntimeException("Unable to create archive: " + file, e); |  | ||||||
|         } |  | ||||||
|         if (lineMapFile.get() != null) { |  | ||||||
|             try { |  | ||||||
|                 lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get())); |  | ||||||
|             } catch (IOException e) { |  | ||||||
|                 throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 		try { | ||||||
|     public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { | 			FileOutputStream fos = new FileOutputStream(file); | ||||||
|         this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null); | 			ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest); | ||||||
|     } | 			outputStreams.put(key, zos); | ||||||
|  | 			saveExecutors.put(key, Executors.newSingleThreadExecutor()); | ||||||
|  | 		} catch (IOException e) { | ||||||
|  | 			throw new RuntimeException("Unable to create archive: " + file, e); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
|     @Override | 		if (lineMapFile.get() != null) { | ||||||
|     public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) { | 			try { | ||||||
|         String key = path + "/" + archiveName; | 				lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get())); | ||||||
|         ExecutorService executor = saveExecutors.get(key); | 			} catch (IOException e) { | ||||||
|         executor.submit(() -> { | 				throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e); | ||||||
|             ZipOutputStream zos = outputStreams.get(key); | 			} | ||||||
|             try { | 		} | ||||||
|                 zos.putNextEntry(new ZipEntry(entryName)); | 	} | ||||||
|                 if (content != null) { |  | ||||||
|                     zos.write(content.getBytes(StandardCharsets.UTF_8)); |  | ||||||
|                 } |  | ||||||
|             } catch (IOException e) { |  | ||||||
|                 DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e); |  | ||||||
|             } |  | ||||||
|             if (mapping != null && lineMapWriter != null) { |  | ||||||
|                 int maxLine = 0; |  | ||||||
|                 int maxLineDest = 0; |  | ||||||
|                 StringBuilder builder = new StringBuilder(); |  | ||||||
|                 for (int i = 0; i < mapping.length; i += 2) { |  | ||||||
|                     maxLine = Math.max(maxLine, mapping[i]); |  | ||||||
|                     maxLineDest = Math.max(maxLineDest, mapping[i + 1]); |  | ||||||
|                     builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n"); |  | ||||||
|                 } |  | ||||||
|                 lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest); |  | ||||||
|                 lineMapWriter.println(builder.toString()); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void closeArchive(String path, String archiveName) { | 	public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { | ||||||
|         String key = path + "/" + archiveName; | 		this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null); | ||||||
|         ExecutorService executor = saveExecutors.get(key); | 	} | ||||||
|         Future<?> closeFuture = executor.submit(() -> { |  | ||||||
|             ZipOutputStream zos = outputStreams.get(key); |  | ||||||
|             try { |  | ||||||
|                 zos.close(); |  | ||||||
|             } catch (IOException e) { |  | ||||||
|                 throw new RuntimeException("Unable to close zip. " + key, e); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         executor.shutdown(); |  | ||||||
|         try { |  | ||||||
|             closeFuture.get(); |  | ||||||
|         } catch (InterruptedException | ExecutionException e) { |  | ||||||
|             throw new RuntimeException(e); |  | ||||||
|         } |  | ||||||
|         outputStreams.remove(key); |  | ||||||
|         saveExecutors.remove(key); |  | ||||||
|         if (lineMapWriter != null) { |  | ||||||
|             lineMapWriter.flush(); |  | ||||||
|             lineMapWriter.close(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     //@formatter:off | 	@Override | ||||||
|     @Override public void saveFolder(String path) { } | 	public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) { | ||||||
|     @Override public void copyFile(String source, String path, String entryName) { } | 		String key = path + "/" + archiveName; | ||||||
|     @Override public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { } | 		ExecutorService executor = saveExecutors.get(key); | ||||||
|     @Override public void saveDirEntry(String path, String archiveName, String entryName) { } | 		executor.submit(() -> { | ||||||
|     @Override public void copyEntry(String source, String path, String archiveName, String entry) { } | 			ZipOutputStream zos = outputStreams.get(key); | ||||||
|     //@formatter:on | 
 | ||||||
|  | 			try { | ||||||
|  | 				zos.putNextEntry(new ZipEntry(entryName)); | ||||||
|  | 
 | ||||||
|  | 				if (content != null) { | ||||||
|  | 					zos.write(content.getBytes(StandardCharsets.UTF_8)); | ||||||
|  | 				} | ||||||
|  | 			} catch (IOException e) { | ||||||
|  | 				DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (mapping != null && lineMapWriter != null) { | ||||||
|  | 				int maxLine = 0; | ||||||
|  | 				int maxLineDest = 0; | ||||||
|  | 				StringBuilder builder = new StringBuilder(); | ||||||
|  | 
 | ||||||
|  | 				for (int i = 0; i < mapping.length; i += 2) { | ||||||
|  | 					maxLine = Math.max(maxLine, mapping[i]); | ||||||
|  | 					maxLineDest = Math.max(maxLineDest, mapping[i + 1]); | ||||||
|  | 					builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n"); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest); | ||||||
|  | 				lineMapWriter.println(builder.toString()); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void closeArchive(String path, String archiveName) { | ||||||
|  | 		String key = path + "/" + archiveName; | ||||||
|  | 		ExecutorService executor = saveExecutors.get(key); | ||||||
|  | 		Future<?> closeFuture = executor.submit(() -> { | ||||||
|  | 			ZipOutputStream zos = outputStreams.get(key); | ||||||
|  | 
 | ||||||
|  | 			try { | ||||||
|  | 				zos.close(); | ||||||
|  | 			} catch (IOException e) { | ||||||
|  | 				throw new RuntimeException("Unable to close zip. " + key, e); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		executor.shutdown(); | ||||||
|  | 
 | ||||||
|  | 		try { | ||||||
|  | 			closeFuture.get(); | ||||||
|  | 		} catch (InterruptedException | ExecutionException e) { | ||||||
|  | 			throw new RuntimeException(e); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		outputStreams.remove(key); | ||||||
|  | 		saveExecutors.remove(key); | ||||||
|  | 
 | ||||||
|  | 		if (lineMapWriter != null) { | ||||||
|  | 			lineMapWriter.flush(); | ||||||
|  | 			lineMapWriter.close(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void saveFolder(String path) { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void copyFile(String source, String path, String entryName) { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void saveDirEntry(String path, String archiveName, String entryName) { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void copyEntry(String source, String path, String archiveName, String entry) { | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,15 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
| import com.google.common.hash.HashCode; | import com.google.common.hash.HashCode; | ||||||
| import com.google.common.hash.Hashing; | import com.google.common.hash.Hashing; | ||||||
| import com.google.common.io.Files; | import com.google.common.io.Files; | ||||||
| import org.gradle.api.logging.Logger; | import org.gradle.api.logging.Logger; | ||||||
| import org.gradle.api.logging.Logging; | import org.gradle.api.logging.Logging; | ||||||
| 
 | 
 | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| 
 |  | ||||||
| public class Checksum { | public class Checksum { | ||||||
| 	private static final Logger log = Logging.getLogger(Checksum.class); | 	private static final Logger log = Logging.getLogger(Checksum.class); | ||||||
| 
 | 
 | ||||||
|  | @ -40,18 +40,22 @@ public class Checksum { | ||||||
| 		if (file == null) { | 		if (file == null) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		try { | 		try { | ||||||
| 			//noinspection deprecation | 			//noinspection deprecation | ||||||
| 			HashCode hash = Files.asByteSource(file).hash(Hashing.sha1()); | 			HashCode hash = Files.asByteSource(file).hash(Hashing.sha1()); | ||||||
| 			StringBuilder builder = new StringBuilder(); | 			StringBuilder builder = new StringBuilder(); | ||||||
|  | 
 | ||||||
| 			for (Byte hashBytes : hash.asBytes()) { | 			for (Byte hashBytes : hash.asBytes()) { | ||||||
| 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); | 			log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); | ||||||
| 			return builder.toString().equals(checksum); | 			return builder.toString().equals(checksum); | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,13 +24,11 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
|  | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import com.google.common.collect.ImmutableList; | import com.google.common.collect.ImmutableList; | ||||||
| 
 | 
 | ||||||
| import java.util.List; |  | ||||||
| 
 |  | ||||||
| public class Constants { | public class Constants { | ||||||
| 
 |  | ||||||
| 	public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker"; | 	public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker"; | ||||||
| 	public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker"; | 	public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker"; | ||||||
| 
 | 
 | ||||||
|  | @ -41,13 +39,9 @@ public class Constants { | ||||||
| 
 | 
 | ||||||
| 	public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath"; | 	public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath"; | ||||||
| 	public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped"; | 	public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped"; | ||||||
| 	public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of( | 	public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), new RemappedConfigurationEntry("modApi", "api", true, "compile"), | ||||||
| 			new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), | 																								new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""), | ||||||
| 			new RemappedConfigurationEntry("modApi", "api", true, "compile"), | 																								new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "")); | ||||||
| 			new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), |  | ||||||
| 			new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""), |  | ||||||
| 			new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "") |  | ||||||
| 	); |  | ||||||
| 
 | 
 | ||||||
| 	public static final String INCLUDE = "include"; | 	public static final String INCLUDE = "include"; | ||||||
| 	public static final String MINECRAFT = "minecraft"; | 	public static final String MINECRAFT = "minecraft"; | ||||||
|  |  | ||||||
|  | @ -32,33 +32,36 @@ import java.util.function.Consumer; | ||||||
|  * Created by covers1624 on 20/12/18. |  * Created by covers1624 on 20/12/18. | ||||||
|  */ |  */ | ||||||
| public class ConsumingOutputStream extends OutputStream { | public class ConsumingOutputStream extends OutputStream { | ||||||
|  | 	private final Consumer<String> consumer; | ||||||
| 
 | 
 | ||||||
|     private final Consumer<String> consumer; | 	private StringBuilder buffer = new StringBuilder(); | ||||||
| 
 | 
 | ||||||
|     private StringBuilder buffer = new StringBuilder(); | 	public ConsumingOutputStream(Consumer<String> consumer) { | ||||||
|  | 		this.consumer = consumer; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     public ConsumingOutputStream(Consumer<String> consumer) { | 	@Override | ||||||
|         this.consumer = consumer; | 	public void write(int b) throws IOException { | ||||||
|     } | 		char ch = (char) (b & 0xFF); | ||||||
|  | 		buffer.append(ch); | ||||||
| 
 | 
 | ||||||
|     @Override | 		if (ch == '\n' || ch == '\r') { | ||||||
|     public void write(int b) throws IOException { | 			flush(); | ||||||
|         char ch = (char) (b & 0xFF); | 		} | ||||||
|         buffer.append(ch); | 	} | ||||||
|         if (ch == '\n' || ch == '\r') { |  | ||||||
|             flush(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @Override | 	@Override | ||||||
|     public void flush() throws IOException { | 	public void flush() throws IOException { | ||||||
|         String str = buffer.toString(); | 		String str = buffer.toString(); | ||||||
|         if (str.endsWith("\r") || str.endsWith("\n")) { | 
 | ||||||
|             str = str.trim(); | 		if (str.endsWith("\r") || str.endsWith("\n")) { | ||||||
|             if (!str.isEmpty()) { | 			str = str.trim(); | ||||||
|                 consumer.accept(str); | 
 | ||||||
|             } | 			if (!str.isEmpty()) { | ||||||
|             buffer = new StringBuilder(); | 				consumer.accept(str); | ||||||
|         } | 			} | ||||||
|     } | 
 | ||||||
|  | 			buffer = new StringBuilder(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,33 +24,8 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.common.collect.ImmutableSet; |  | ||||||
| import com.google.common.collect.Iterables; |  | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| 
 |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| 
 |  | ||||||
| import org.apache.commons.io.FilenameUtils; |  | ||||||
| import org.gradle.api.InvalidUserDataException; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.artifacts.Configuration; |  | ||||||
| import org.gradle.api.artifacts.Dependency; |  | ||||||
| import org.gradle.api.artifacts.ResolvedArtifact; |  | ||||||
| import org.gradle.api.artifacts.ResolvedDependency; |  | ||||||
| import org.gradle.api.artifacts.SelfResolvingDependency; |  | ||||||
| import org.gradle.api.artifacts.query.ArtifactResolutionQuery; |  | ||||||
| import org.gradle.api.artifacts.result.ArtifactResult; |  | ||||||
| import org.gradle.api.artifacts.result.ComponentArtifactsResult; |  | ||||||
| import org.gradle.api.artifacts.result.ResolvedArtifactResult; |  | ||||||
| import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier; |  | ||||||
| import org.gradle.jvm.JvmLibrary; |  | ||||||
| import org.gradle.language.base.artifact.SourcesArtifact; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.Comparator; | import java.util.Comparator; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | @ -60,8 +35,21 @@ import java.util.Set; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
| public abstract class DependencyProvider { | import com.google.common.collect.Iterables; | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import org.apache.commons.io.FilenameUtils; | ||||||
|  | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.gradle.api.InvalidUserDataException; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.artifacts.Configuration; | ||||||
|  | import org.gradle.api.artifacts.Dependency; | ||||||
|  | import org.gradle.api.artifacts.ResolvedDependency; | ||||||
|  | import org.gradle.api.artifacts.SelfResolvingDependency; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | 
 | ||||||
|  | public abstract class DependencyProvider { | ||||||
| 	private LoomDependencyManager dependencyManager; | 	private LoomDependencyManager dependencyManager; | ||||||
| 
 | 
 | ||||||
| 	public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception; | 	public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception; | ||||||
|  | @ -73,13 +61,14 @@ public abstract class DependencyProvider { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void addDependency(Object object, Project project, String target) { | 	public void addDependency(Object object, Project project, String target) { | ||||||
| 		if(object instanceof File){ | 		if (object instanceof File) { | ||||||
| 			object = project.files(object); | 			object = project.files(object); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		project.getDependencies().add(target, object); | 		project.getDependencies().add(target, object); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void register(LoomDependencyManager dependencyManager){ | 	public void register(LoomDependencyManager dependencyManager) { | ||||||
| 		this.dependencyManager = dependencyManager; | 		this.dependencyManager = dependencyManager; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -132,14 +121,17 @@ public abstract class DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 		public Optional<File> resolveFile() { | 		public Optional<File> resolveFile() { | ||||||
| 			Set<File> files = resolve(); | 			Set<File> files = resolve(); | ||||||
|  | 
 | ||||||
| 			if (files.isEmpty()) { | 			if (files.isEmpty()) { | ||||||
| 				return Optional.empty(); | 				return Optional.empty(); | ||||||
| 			} else if (files.size() > 1) { | 			} else if (files.size() > 1) { | ||||||
| 				StringBuilder builder = new StringBuilder(this.toString()); | 				StringBuilder builder = new StringBuilder(this.toString()); | ||||||
| 				builder.append(" resolves to more than one file:"); | 				builder.append(" resolves to more than one file:"); | ||||||
|  | 
 | ||||||
| 				for (File f : files) { | 				for (File f : files) { | ||||||
| 					builder.append("\n\t-").append(f.getAbsolutePath()); | 					builder.append("\n\t-").append(f.getAbsolutePath()); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				throw new RuntimeException(builder.toString()); | 				throw new RuntimeException(builder.toString()); | ||||||
| 			} else { | 			} else { | ||||||
| 				return files.stream().findFirst(); | 				return files.stream().findFirst(); | ||||||
|  | @ -151,11 +143,11 @@ public abstract class DependencyProvider { | ||||||
| 			return getDepString(); | 			return getDepString(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public String getDepString(){ | 		public String getDepString() { | ||||||
| 			return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion(); | 			return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public String getResolvedDepString(){ | 		public String getResolvedDepString() { | ||||||
| 			return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion(); | 			return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -178,7 +170,6 @@ public abstract class DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 			default: //File collection, try work out the classifiers | 			default: //File collection, try work out the classifiers | ||||||
| 				List<File> sortedFiles = files.stream().sorted(Comparator.comparing(File::getName, Comparator.comparingInt(String::length))).collect(Collectors.toList()); | 				List<File> sortedFiles = files.stream().sorted(Comparator.comparing(File::getName, Comparator.comparingInt(String::length))).collect(Collectors.toList()); | ||||||
| 
 |  | ||||||
| 				//First element in sortedFiles is the one with the shortest name, we presume all the others are different classifier types of this | 				//First element in sortedFiles is the one with the shortest name, we presume all the others are different classifier types of this | ||||||
| 				File shortest = sortedFiles.remove(0); | 				File shortest = sortedFiles.remove(0); | ||||||
| 				String shortestName = FilenameUtils.removeExtension(shortest.getName()); //name.jar -> name | 				String shortestName = FilenameUtils.removeExtension(shortest.getName()); //name.jar -> name | ||||||
|  | @ -192,8 +183,8 @@ public abstract class DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 				//We appear to be right, therefore this is the normal dependency file we want | 				//We appear to be right, therefore this is the normal dependency file we want | ||||||
| 				classifierToFile.put("", shortest); | 				classifierToFile.put("", shortest); | ||||||
| 
 |  | ||||||
| 				int start = shortestName.length(); | 				int start = shortestName.length(); | ||||||
|  | 
 | ||||||
| 				for (File file : sortedFiles) { | 				for (File file : sortedFiles) { | ||||||
| 					//Now we just have to work out what classifier type the other files are, this shouldn't even return an empty string | 					//Now we just have to work out what classifier type the other files are, this shouldn't even return an empty string | ||||||
| 					String classifier = FilenameUtils.removeExtension(file.getName()).substring(start); | 					String classifier = FilenameUtils.removeExtension(file.getName()).substring(start); | ||||||
|  | @ -206,16 +197,21 @@ public abstract class DependencyProvider { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			File root = classifierToFile.get(""); //We've built the classifierToFile map, now to try find a name and version for our dependency | 			File root = classifierToFile.get(""); //We've built the classifierToFile map, now to try find a name and version for our dependency | ||||||
|  | 
 | ||||||
| 			if ("jar".equals(FilenameUtils.getExtension(root.getName())) && ZipUtil.containsEntry(root, "fabric.mod.json")) { | 			if ("jar".equals(FilenameUtils.getExtension(root.getName())) && ZipUtil.containsEntry(root, "fabric.mod.json")) { | ||||||
| 				//It's a Fabric mod, see how much we can extract out | 				//It's a Fabric mod, see how much we can extract out | ||||||
| 				JsonObject json = new Gson().fromJson(new String(ZipUtil.unpackEntry(root, "fabric.mod.json"), StandardCharsets.UTF_8), JsonObject.class); | 				JsonObject json = new Gson().fromJson(new String(ZipUtil.unpackEntry(root, "fabric.mod.json"), StandardCharsets.UTF_8), JsonObject.class); | ||||||
| 				if (json == null || !json.has("id") || !json.has("version")) throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')'); |  | ||||||
| 
 | 
 | ||||||
| 				if (json.has("name")) {//Go for the name field if it's got one | 				if (json == null || !json.has("id") || !json.has("version")) { | ||||||
|  | 					throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')'); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (json.has("name")) { //Go for the name field if it's got one | ||||||
| 					name = json.get("name").getAsString(); | 					name = json.get("name").getAsString(); | ||||||
| 				} else { | 				} else { | ||||||
| 					name = json.get("id").getAsString(); | 					name = json.get("id").getAsString(); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				version = json.get("version").getAsString(); | 				version = json.get("version").getAsString(); | ||||||
| 			} else { | 			} else { | ||||||
| 				//Not a Fabric mod, just have to make something up | 				//Not a Fabric mod, just have to make something up | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  * SOFTWARE. |  * SOFTWARE. | ||||||
|  */ |  */ | ||||||
|  | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  | @ -29,21 +30,18 @@ import java.net.HttpURLConnection; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| 
 | 
 | ||||||
|  | import com.google.common.io.Files; | ||||||
| import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||||
| 
 |  | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.logging.Logger; | import org.gradle.api.logging.Logger; | ||||||
| 
 | 
 | ||||||
| import com.google.common.io.Files; |  | ||||||
| 
 |  | ||||||
| public class DownloadUtil { | public class DownloadUtil { | ||||||
| 	/** | 	/** | ||||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them | 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param from The URL of the file to be downloaded | 	 * @param from The URL of the file to be downloaded | ||||||
| 	 * @param to The destination to be saved to, and compared against if it exists | 	 * @param to The destination to be saved to, and compared against if it exists | ||||||
| 	 * @param logger The logger to print everything to, typically from {@link Project#getLogger()} | 	 * @param logger The logger to print everything to, typically from {@link Project#getLogger()} | ||||||
| 	 * |  | ||||||
| 	 * @throws IOException If an exception occurs during the process | 	 * @throws IOException If an exception occurs during the process | ||||||
| 	 */ | 	 */ | ||||||
| 	public static void downloadIfChanged(URL from, File to, Logger logger) throws IOException { | 	public static void downloadIfChanged(URL from, File to, Logger logger) throws IOException { | ||||||
|  | @ -51,24 +49,28 @@ public class DownloadUtil { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them | 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param from The URL of the file to be downloaded | 	 * @param from The URL of the file to be downloaded | ||||||
| 	 * @param to The destination to be saved to, and compared against if it exists | 	 * @param to The destination to be saved to, and compared against if it exists | ||||||
| 	 * @param logger The logger to print information to, typically from {@link Project#getLogger()} | 	 * @param logger The logger to print information to, typically from {@link Project#getLogger()} | ||||||
| 	 * @param quiet Whether to only print warnings (when <code>true</code>) or everything | 	 * @param quiet Whether to only print warnings (when <code>true</code>) or everything | ||||||
| 	 * |  | ||||||
| 	 * @throws IOException If an exception occurs during the process | 	 * @throws IOException If an exception occurs during the process | ||||||
| 	 */ | 	 */ | ||||||
| 	public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException { | 	public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException { | ||||||
| 		HttpURLConnection connection = (HttpURLConnection) from.openConnection(); | 		HttpURLConnection connection = (HttpURLConnection) from.openConnection(); | ||||||
| 
 | 
 | ||||||
| 		//If the output already exists we'll use it's last modified time | 		//If the output already exists we'll use it's last modified time | ||||||
| 		if (to.exists()) connection.setIfModifiedSince(to.lastModified()); | 		if (to.exists()) { | ||||||
|  | 			connection.setIfModifiedSince(to.lastModified()); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		//Try use the ETag if there's one for the file we're downloading | 		//Try use the ETag if there's one for the file we're downloading | ||||||
| 		String etag = loadETag(to, logger); | 		String etag = loadETag(to, logger); | ||||||
| 		if (etag != null) connection.setRequestProperty("If-None-Match", etag); | 
 | ||||||
|  | 		if (etag != null) { | ||||||
|  | 			connection.setRequestProperty("If-None-Match", etag); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		//We want to download gzip compressed stuff | 		//We want to download gzip compressed stuff | ||||||
| 		connection.setRequestProperty("Accept-Encoding", "gzip"); | 		connection.setRequestProperty("Accept-Encoding", "gzip"); | ||||||
|  | @ -80,21 +82,29 @@ public class DownloadUtil { | ||||||
| 		connection.connect(); | 		connection.connect(); | ||||||
| 
 | 
 | ||||||
| 		int code = connection.getResponseCode(); | 		int code = connection.getResponseCode(); | ||||||
|  | 
 | ||||||
| 		if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { | 		if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { | ||||||
| 			//Didn't get what we expected | 			//Didn't get what we expected | ||||||
| 			throw new IOException(connection.getResponseMessage()); | 			throw new IOException(connection.getResponseMessage()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1); | 		long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1); | ||||||
|  | 
 | ||||||
| 		if (to.exists() && (code == HttpURLConnection.HTTP_NOT_MODIFIED || modifyTime > 0 && to.lastModified() >= modifyTime)) { | 		if (to.exists() && (code == HttpURLConnection.HTTP_NOT_MODIFIED || modifyTime > 0 && to.lastModified() >= modifyTime)) { | ||||||
| 			if (!quiet) logger.info("'{}' Not Modified, skipping.", to); | 			if (!quiet) { | ||||||
|  | 				logger.info("'{}' Not Modified, skipping.", to); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			return; //What we've got is already fine | 			return; //What we've got is already fine | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		long contentLength = connection.getContentLengthLong(); | 		long contentLength = connection.getContentLengthLong(); | ||||||
| 		if (!quiet && contentLength >= 0) logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength)); |  | ||||||
| 
 | 
 | ||||||
| 		try {//Try download to the output | 		if (!quiet && contentLength >= 0) { | ||||||
|  | 			logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		try { //Try download to the output | ||||||
| 			FileUtils.copyInputStreamToFile(connection.getInputStream(), to); | 			FileUtils.copyInputStreamToFile(connection.getInputStream(), to); | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			to.delete(); //Probably isn't good if it fails to copy/save | 			to.delete(); //Probably isn't good if it fails to copy/save | ||||||
|  | @ -102,23 +112,27 @@ public class DownloadUtil { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		//Set the modify time to match the server's (if we know it) | 		//Set the modify time to match the server's (if we know it) | ||||||
| 		if (modifyTime > 0) to.setLastModified(modifyTime); | 		if (modifyTime > 0) { | ||||||
|  | 			to.setLastModified(modifyTime); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		//Save the ETag (if we know it) | 		//Save the ETag (if we know it) | ||||||
| 		String eTag = connection.getHeaderField("ETag"); | 		String eTag = connection.getHeaderField("ETag"); | ||||||
|  | 
 | ||||||
| 		if (eTag != null) { | 		if (eTag != null) { | ||||||
| 			//Log if we get a weak ETag and we're not on quiet | 			//Log if we get a weak ETag and we're not on quiet | ||||||
| 			if (!quiet && eTag.startsWith("W/")) logger.warn("Weak ETag found."); | 			if (!quiet && eTag.startsWith("W/")) { | ||||||
|  | 				logger.warn("Weak ETag found."); | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			saveETag(to, eTag, logger); | 			saveETag(to, eTag, logger); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name | 	 * Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param file The file to produce the ETag for | 	 * @param file The file to produce the ETag for | ||||||
| 	 * |  | ||||||
| 	 * @return The (uncreated) ETag file for the given file | 	 * @return The (uncreated) ETag file for the given file | ||||||
| 	 */ | 	 */ | ||||||
| 	private static File getETagFile(File file) { | 	private static File getETagFile(File file) { | ||||||
|  | @ -126,16 +140,18 @@ public class DownloadUtil { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Attempt to load an ETag for the given file, if it exists | 	 * Attempt to load an ETag for the given file, if it exists. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param to The file to load an ETag for | 	 * @param to The file to load an ETag for | ||||||
| 	 * @param logger The logger to print errors to if it goes wrong | 	 * @param logger The logger to print errors to if it goes wrong | ||||||
| 	 * |  | ||||||
| 	 * @return The ETag for the given file, or <code>null</code> if it doesn't exist | 	 * @return The ETag for the given file, or <code>null</code> if it doesn't exist | ||||||
| 	 */ | 	 */ | ||||||
| 	private static String loadETag(File to, Logger logger) { | 	private static String loadETag(File to, Logger logger) { | ||||||
| 		File eTagFile = getETagFile(to); | 		File eTagFile = getETagFile(to); | ||||||
| 		if (!eTagFile.exists()) return null; | 
 | ||||||
|  | 		if (!eTagFile.exists()) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			return Files.asCharSource(eTagFile, StandardCharsets.UTF_8).read(); | 			return Files.asCharSource(eTagFile, StandardCharsets.UTF_8).read(); | ||||||
|  | @ -146,7 +162,7 @@ public class DownloadUtil { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Saves the given ETag for the given file, replacing it if it already exists | 	 * Saves the given ETag for the given file, replacing it if it already exists. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param to The file to save the ETag for | 	 * @param to The file to save the ETag for | ||||||
| 	 * @param eTag The ETag to be saved | 	 * @param eTag The ETag to be saved | ||||||
|  | @ -154,8 +170,12 @@ public class DownloadUtil { | ||||||
| 	 */ | 	 */ | ||||||
| 	private static void saveETag(File to, String eTag, Logger logger) { | 	private static void saveETag(File to, String eTag, Logger logger) { | ||||||
| 		File eTagFile = getETagFile(to); | 		File eTagFile = getETagFile(to); | ||||||
|  | 
 | ||||||
| 		try { | 		try { | ||||||
| 			if (!eTagFile.exists()) eTagFile.createNewFile(); | 			if (!eTagFile.exists()) { | ||||||
|  | 				eTagFile.createNewFile(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag); | 			Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag); | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			logger.warn("Error saving ETag file '{}'.", eTagFile, e); | 			logger.warn("Error saving ETag file '{}'.", eTagFile, e); | ||||||
|  | @ -163,10 +183,9 @@ public class DownloadUtil { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Format the given number of bytes as a more human readable string | 	 * Format the given number of bytes as a more human readable string. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param bytes The number of bytes | 	 * @param bytes The number of bytes | ||||||
| 	 * |  | ||||||
| 	 * @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate | 	 * @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate | ||||||
| 	 */ | 	 */ | ||||||
| 	private static String toNiceSize(long bytes) { | 	private static String toNiceSize(long bytes) { | ||||||
|  | @ -192,8 +211,9 @@ public class DownloadUtil { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		File etagFile = getETagFile(file); | 		File etagFile = getETagFile(file); | ||||||
|  | 
 | ||||||
| 		if (etagFile.exists()) { | 		if (etagFile.exists()) { | ||||||
| 			etagFile.delete(); | 			etagFile.delete(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,23 +24,23 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | 
 | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.file.RegularFileProperty; | import org.gradle.api.file.RegularFileProperty; | ||||||
| import org.gradle.api.model.ObjectFactory; | import org.gradle.api.model.ObjectFactory; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.InvocationTargetException; |  | ||||||
| import java.lang.reflect.Method; |  | ||||||
| 
 |  | ||||||
| //This is used to bridge the gap over large gradle api changes. | //This is used to bridge the gap over large gradle api changes. | ||||||
| public class GradleSupport { | public class GradleSupport { | ||||||
| 
 | 	public static RegularFileProperty getfileProperty(Project project) { | ||||||
| 	public static RegularFileProperty getfileProperty(Project project){ |  | ||||||
| 		try { | 		try { | ||||||
| 			//First try the new method, if that fails fall back. | 			//First try the new method, if that fails fall back. | ||||||
| 			return getfilePropertyModern(project); | 			return getfilePropertyModern(project); | ||||||
| 		} catch (Exception e){ | 		} catch (Exception e) { | ||||||
| 			//Nope | 			//Nope | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return getfilePropertyLegacy(project); | 		return getfilePropertyLegacy(project); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -51,7 +51,7 @@ public class GradleSupport { | ||||||
| 		return (RegularFileProperty) method.invoke(objectFactory); | 		return (RegularFileProperty) method.invoke(objectFactory); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static RegularFileProperty getfilePropertyLegacy(Project project){ | 	private static RegularFileProperty getfilePropertyLegacy(Project project) { | ||||||
| 		return project.getLayout().fileProperty(); | 		return project.getLayout().fileProperty(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,17 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import groovy.util.Node; |  | ||||||
| 
 |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| import java.util.stream.Stream; | import java.util.stream.Stream; | ||||||
| 
 | 
 | ||||||
| public final class GroovyXmlUtil { | import groovy.util.Node; | ||||||
| 	private GroovyXmlUtil() { |  | ||||||
| 
 | 
 | ||||||
| 	} | public final class GroovyXmlUtil { | ||||||
|  | 	private GroovyXmlUtil() { } | ||||||
| 
 | 
 | ||||||
| 	public static Node getOrCreateNode(Node parent, String name) { | 	public static Node getOrCreateNode(Node parent, String name) { | ||||||
| 		for (Object object : parent.children()) { | 		for (Object object : parent.children()) { | ||||||
|  |  | ||||||
|  | @ -24,138 +24,160 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | import static java.text.MessageFormat.format; | ||||||
| import org.gradle.api.logging.Logger; |  | ||||||
| import org.objectweb.asm.*; |  | ||||||
| 
 | 
 | ||||||
| import java.io.*; | import java.io.BufferedReader; | ||||||
| import java.nio.file.*; | import java.io.File; | ||||||
|  | import java.io.FileReader; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.nio.file.FileVisitResult; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.SimpleFileVisitor; | ||||||
|  | import java.nio.file.StandardCopyOption; | ||||||
| import java.nio.file.attribute.BasicFileAttributes; | import java.nio.file.attribute.BasicFileAttributes; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
| import static java.text.MessageFormat.format; | import org.objectweb.asm.ClassReader; | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.ClassWriter; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.util.progress.ProgressLogger; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * TODO, Move to stitch. |  * TODO, Move to stitch. | ||||||
|  * Created by covers1624 on 18/02/19. |  * Created by covers1624 on 18/02/19. | ||||||
|  */ |  */ | ||||||
| public class LineNumberRemapper { | public class LineNumberRemapper { | ||||||
|  | 	private final Map<String, RClass> lineMap = new HashMap<>(); | ||||||
| 
 | 
 | ||||||
|     private final Map<String, RClass> lineMap = new HashMap<>(); | 	public void readMappings(File lineMappings) { | ||||||
|  | 		try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { | ||||||
|  | 			RClass clazz = null; | ||||||
|  | 			String line = null; | ||||||
|  | 			int i = 0; | ||||||
| 
 | 
 | ||||||
|     public void readMappings(File lineMappings) { | 			try { | ||||||
|         try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { | 				while ((line = reader.readLine()) != null) { | ||||||
|             RClass clazz = null; | 					if (line.isEmpty()) { | ||||||
|             String line = null; | 						continue; | ||||||
|             int i = 0; | 					} | ||||||
|             try { |  | ||||||
|                 while ((line = reader.readLine()) != null) { |  | ||||||
|                     if (line.isEmpty()) { |  | ||||||
|                         continue; |  | ||||||
|                     } |  | ||||||
|                     String[] segs = line.trim().split("\t"); |  | ||||||
|                     if (line.charAt(0) != '\t') { |  | ||||||
|                         clazz = lineMap.computeIfAbsent(segs[0], RClass::new); |  | ||||||
|                         clazz.maxLine = Integer.parseInt(segs[1]); |  | ||||||
|                         clazz.maxLineDest = Integer.parseInt(segs[2]); |  | ||||||
|                     } else { |  | ||||||
|                         clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1])); |  | ||||||
|                     } |  | ||||||
|                     i++; |  | ||||||
|                 } |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e); |  | ||||||
|             } |  | ||||||
|         } catch (IOException e) { |  | ||||||
|             throw new RuntimeException("Exception reading LineMappings file.", e); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     public void process(ProgressLogger logger, Path input, Path output) throws IOException { | 					String[] segs = line.trim().split("\t"); | ||||||
|         Files.walkFileTree(input, new SimpleFileVisitor<Path>() { |  | ||||||
|             @Override |  | ||||||
|             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { |  | ||||||
|                 String rel = input.relativize(file).toString(); |  | ||||||
|                 Path dst = output.resolve(rel); |  | ||||||
|                 Path parent = dst.getParent(); |  | ||||||
|                 if (parent != null) { |  | ||||||
|                     Files.createDirectories(parent); |  | ||||||
|                 } |  | ||||||
|                 String fName = file.getFileName().toString(); |  | ||||||
|                 if (fName.endsWith(".class")) { |  | ||||||
|                     if (Files.exists(dst)) { |  | ||||||
|                         Files.delete(dst); |  | ||||||
|                     } |  | ||||||
|                     String idx = rel.substring(0, rel.length() - 6); |  | ||||||
|                     if (logger != null) { |  | ||||||
|                         logger.progress("Remapping " + idx); |  | ||||||
|                     } |  | ||||||
| 
 | 
 | ||||||
|                     int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped. | 					if (line.charAt(0) != '\t') { | ||||||
|                     if (dollarPos >= 0) { | 						clazz = lineMap.computeIfAbsent(segs[0], RClass::new); | ||||||
|                         idx = idx.substring(0, dollarPos); | 						clazz.maxLine = Integer.parseInt(segs[1]); | ||||||
|                     } | 						clazz.maxLineDest = Integer.parseInt(segs[2]); | ||||||
|                     if (lineMap.containsKey(idx)) { | 					} else { | ||||||
|                         try (InputStream is = Files.newInputStream(file)) { | 						clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1])); | ||||||
|                             ClassReader reader = new ClassReader(is); | 					} | ||||||
|                             ClassWriter writer = new ClassWriter(0); |  | ||||||
| 
 | 
 | ||||||
|                             reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0); | 					i++; | ||||||
|                             Files.write(dst, writer.toByteArray()); | 				} | ||||||
|                         } | 			} catch (Exception e) { | ||||||
|                     } | 				throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e); | ||||||
|  | 			} | ||||||
|  | 		} catch (IOException e) { | ||||||
|  | 			throw new RuntimeException("Exception reading LineMappings file.", e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|                 } else { | 	public void process(ProgressLogger logger, Path input, Path output) throws IOException { | ||||||
|                     Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); | 		Files.walkFileTree(input, new SimpleFileVisitor<Path>() { | ||||||
|                 } | 			@Override | ||||||
|  | 			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { | ||||||
|  | 				String rel = input.relativize(file).toString(); | ||||||
|  | 				Path dst = output.resolve(rel); | ||||||
|  | 				Path parent = dst.getParent(); | ||||||
| 
 | 
 | ||||||
|                 return FileVisitResult.CONTINUE; | 				if (parent != null) { | ||||||
|             } | 					Files.createDirectories(parent); | ||||||
|         }); | 				} | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static class LineNumberVisitor extends ClassVisitor { | 				String fName = file.getFileName().toString(); | ||||||
| 
 | 
 | ||||||
|         private final RClass rClass; | 				if (fName.endsWith(".class")) { | ||||||
|  | 					if (Files.exists(dst)) { | ||||||
|  | 						Files.delete(dst); | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
|         public LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { | 					String idx = rel.substring(0, rel.length() - 6); | ||||||
|             super(api, classVisitor); |  | ||||||
|             this.rClass = rClass; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         @Override | 					if (logger != null) { | ||||||
|         public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { | 						logger.progress("Remapping " + idx); | ||||||
|             return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { | 					} | ||||||
|                 @Override |  | ||||||
|                 public void visitLineNumber(int line, Label start) { |  | ||||||
|                     int tLine = line; |  | ||||||
|                     if (tLine <= 0) { |  | ||||||
|                         super.visitLineNumber(line, start); |  | ||||||
|                     } else if (tLine >= rClass.maxLine) { |  | ||||||
|                         super.visitLineNumber(rClass.maxLineDest, start); |  | ||||||
|                     } else { |  | ||||||
|                         Integer matchedLine = null; |  | ||||||
|                         while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) { |  | ||||||
|                             tLine++; |  | ||||||
|                         } |  | ||||||
|                         super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static class RClass { | 					int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped. | ||||||
| 
 | 
 | ||||||
|         private final String name; | 					if (dollarPos >= 0) { | ||||||
|         private int maxLine; | 						idx = idx.substring(0, dollarPos); | ||||||
|         private int maxLineDest; | 					} | ||||||
|         private Map<Integer, Integer> lineMap = new HashMap<>(); |  | ||||||
| 
 | 
 | ||||||
|         private RClass(String name) { | 					if (lineMap.containsKey(idx)) { | ||||||
|             this.name = name; | 						try (InputStream is = Files.newInputStream(file)) { | ||||||
|         } | 							ClassReader reader = new ClassReader(is); | ||||||
|     } | 							ClassWriter writer = new ClassWriter(0); | ||||||
| 
 | 
 | ||||||
|  | 							reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0); | ||||||
|  | 							Files.write(dst, writer.toByteArray()); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				return FileVisitResult.CONTINUE; | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static class LineNumberVisitor extends ClassVisitor { | ||||||
|  | 		private final RClass rClass; | ||||||
|  | 
 | ||||||
|  | 		LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { | ||||||
|  | 			super(api, classVisitor); | ||||||
|  | 			this.rClass = rClass; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		@Override | ||||||
|  | 		public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { | ||||||
|  | 			return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { | ||||||
|  | 				@Override | ||||||
|  | 				public void visitLineNumber(int line, Label start) { | ||||||
|  | 					int tLine = line; | ||||||
|  | 
 | ||||||
|  | 					if (tLine <= 0) { | ||||||
|  | 						super.visitLineNumber(line, start); | ||||||
|  | 					} else if (tLine >= rClass.maxLine) { | ||||||
|  | 						super.visitLineNumber(rClass.maxLineDest, start); | ||||||
|  | 					} else { | ||||||
|  | 						Integer matchedLine = null; | ||||||
|  | 
 | ||||||
|  | 						while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) { | ||||||
|  | 							tLine++; | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static class RClass { | ||||||
|  | 		private final String name; | ||||||
|  | 		private int maxLine; | ||||||
|  | 		private int maxLineDest; | ||||||
|  | 		private Map<Integer, Integer> lineMap = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  | 		private RClass(String name) { | ||||||
|  | 			this.name = name; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,19 +24,24 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.JsonObject; | import java.io.File; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.util.ArrayList; | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; | import java.util.HashMap; | ||||||
| import net.fabricmc.loom.util.DependencyProvider.DependencyInfo; | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Set; | ||||||
| 
 | 
 | ||||||
|  | import com.google.gson.JsonObject; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.artifacts.Configuration; | import org.gradle.api.artifacts.Configuration; | ||||||
| import org.gradle.api.artifacts.Dependency; | import org.gradle.api.artifacts.Dependency; | ||||||
| import org.gradle.api.artifacts.ExternalModuleDependency; | import org.gradle.api.artifacts.ExternalModuleDependency; | ||||||
| import org.gradle.api.artifacts.repositories.MavenArtifactRepository; | import org.gradle.api.artifacts.repositories.MavenArtifactRepository; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import java.util.*; | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
|  | import net.fabricmc.loom.util.DependencyProvider.DependencyInfo; | ||||||
| 
 | 
 | ||||||
| public class LoomDependencyManager { | public class LoomDependencyManager { | ||||||
| 	private static class ProviderList { | 	private static class ProviderList { | ||||||
|  | @ -50,27 +55,30 @@ public class LoomDependencyManager { | ||||||
| 
 | 
 | ||||||
| 	private List<DependencyProvider> dependencyProviderList = new ArrayList<>(); | 	private List<DependencyProvider> dependencyProviderList = new ArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 	public void addProvider(DependencyProvider provider){ | 	public void addProvider(DependencyProvider provider) { | ||||||
| 		if(dependencyProviderList.contains(provider)){ | 		if (dependencyProviderList.contains(provider)) { | ||||||
| 			throw new RuntimeException("Provider is already registered"); | 			throw new RuntimeException("Provider is already registered"); | ||||||
| 		} | 		} | ||||||
| 		if(getProvider(provider.getClass()) != null){ | 
 | ||||||
|  | 		if (getProvider(provider.getClass()) != null) { | ||||||
| 			throw new RuntimeException("Provider of this type is already registered"); | 			throw new RuntimeException("Provider of this type is already registered"); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		provider.register(this); | 		provider.register(this); | ||||||
| 		dependencyProviderList.add(provider); | 		dependencyProviderList.add(provider); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public <T> T getProvider(Class<T> clazz){ | 	public <T> T getProvider(Class<T> clazz) { | ||||||
| 		for(DependencyProvider provider : dependencyProviderList){ | 		for (DependencyProvider provider : dependencyProviderList) { | ||||||
| 			if(provider.getClass() == clazz){ | 			if (provider.getClass() == clazz) { | ||||||
| 				return (T) provider; | 				return (T) provider; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void handleDependencies(Project project){ | 	public void handleDependencies(Project project) { | ||||||
| 		List<Runnable> afterTasks = new ArrayList<>(); | 		List<Runnable> afterTasks = new ArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 		MappingsProvider mappingsProvider = null; | 		MappingsProvider mappingsProvider = null; | ||||||
|  | @ -80,7 +88,7 @@ public class LoomDependencyManager { | ||||||
| 		Map<String, ProviderList> providerListMap = new HashMap<>(); | 		Map<String, ProviderList> providerListMap = new HashMap<>(); | ||||||
| 		List<ProviderList> targetProviders = new ArrayList<>(); | 		List<ProviderList> targetProviders = new ArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 		for(DependencyProvider provider : dependencyProviderList){ | 		for (DependencyProvider provider : dependencyProviderList) { | ||||||
| 			providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> { | 			providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> { | ||||||
| 				ProviderList list = new ProviderList(k); | 				ProviderList list = new ProviderList(k); | ||||||
| 				targetProviders.add(list); | 				targetProviders.add(list); | ||||||
|  | @ -101,6 +109,7 @@ public class LoomDependencyManager { | ||||||
| 			configuration.getDependencies().forEach(dependency -> { | 			configuration.getDependencies().forEach(dependency -> { | ||||||
| 				for (DependencyProvider provider : list.providers) { | 				for (DependencyProvider provider : list.providers) { | ||||||
| 					DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | 					DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | ||||||
|  | 
 | ||||||
| 					try { | 					try { | ||||||
| 						provider.provide(info, project, extension, afterTasks::add); | 						provider.provide(info, project, extension, afterTasks::add); | ||||||
| 					} catch (Exception e) { | 					} catch (Exception e) { | ||||||
|  | @ -114,13 +123,7 @@ public class LoomDependencyManager { | ||||||
| 			String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion; | 			String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion; | ||||||
| 
 | 
 | ||||||
| 			for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | 			for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | ||||||
| 				ModCompileRemapper.remapDependencies( | 				ModCompileRemapper.remapDependencies(project, mappingsKey, extension, project.getConfigurations().getByName(entry.getSourceConfiguration()), project.getConfigurations().getByName(entry.getRemappedConfiguration()), project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), afterTasks::add); | ||||||
| 						project, mappingsKey, extension, |  | ||||||
| 						project.getConfigurations().getByName(entry.getSourceConfiguration()), |  | ||||||
| 						project.getConfigurations().getByName(entry.getRemappedConfiguration()), |  | ||||||
| 						project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), |  | ||||||
| 						afterTasks::add |  | ||||||
| 				); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -133,9 +136,11 @@ public class LoomDependencyManager { | ||||||
| 
 | 
 | ||||||
| 			for (Dependency dependency : configuration.getDependencies()) { | 			for (Dependency dependency : configuration.getDependencies()) { | ||||||
| 				DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | 				DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | ||||||
|  | 
 | ||||||
| 				for (File input : info.resolve()) { | 				for (File input : info.resolve()) { | ||||||
| 					if (seenFiles.add(input)) { | 					if (seenFiles.add(input)) { | ||||||
| 						ModProcessor.readInstallerJson(input, project); | 						ModProcessor.readInstallerJson(input, project); | ||||||
|  | 
 | ||||||
| 						if (extension.getInstallerJson() != null) { | 						if (extension.getInstallerJson() != null) { | ||||||
| 							project.getLogger().info("Found installer JSON in " + info); | 							project.getLogger().info("Found installer JSON in " + info); | ||||||
| 							break; //Found it, probably don't need to look any further | 							break; //Found it, probably don't need to look any further | ||||||
|  | @ -156,7 +161,7 @@ public class LoomDependencyManager { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void handleInstallerJson(JsonObject jsonObject, Project project){ | 	private static void handleInstallerJson(JsonObject jsonObject, Project project) { | ||||||
| 		JsonObject libraries = jsonObject.get("libraries").getAsJsonObject(); | 		JsonObject libraries = jsonObject.get("libraries").getAsJsonObject(); | ||||||
| 		Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES); | 		Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES); | ||||||
| 		Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor"); | 		Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor"); | ||||||
|  | @ -171,16 +176,15 @@ public class LoomDependencyManager { | ||||||
| 
 | 
 | ||||||
| 			project.getLogger().debug("Loom adding " + name + " from installer JSON"); | 			project.getLogger().debug("Loom adding " + name + " from installer JSON"); | ||||||
| 
 | 
 | ||||||
| 			if(jsonElement.getAsJsonObject().has("url")){ | 			if (jsonElement.getAsJsonObject().has("url")) { | ||||||
| 				String url = jsonElement.getAsJsonObject().get("url").getAsString(); | 				String url = jsonElement.getAsJsonObject().get("url").getAsString(); | ||||||
| 				long count = project.getRepositories().stream() | 				long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository) | ||||||
| 						.filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository) |  | ||||||
| 						.map(artifactRepository -> (MavenArtifactRepository) artifactRepository) | 						.map(artifactRepository -> (MavenArtifactRepository) artifactRepository) | ||||||
| 						.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count(); | 						.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count(); | ||||||
| 				if(count == 0){ | 
 | ||||||
|  | 				if (count == 0) { | ||||||
| 					project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString())); | 					project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString())); | ||||||
| 				} | 				} | ||||||
| 
 |  | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -24,32 +24,28 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftProvider; |  | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; |  | ||||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; |  | ||||||
| import net.fabricmc.tinyremapper.TinyRemapper; |  | ||||||
| import net.fabricmc.tinyremapper.TinyUtils; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| 
 | 
 | ||||||
| public class MapJarsTiny { | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftProvider; | ||||||
|  | import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||||
|  | import net.fabricmc.tinyremapper.TinyRemapper; | ||||||
|  | 
 | ||||||
|  | public class MapJarsTiny { | ||||||
| 	public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, Project project) throws IOException { | 	public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, Project project) throws IOException { | ||||||
| 		String fromM = "official"; | 		String fromM = "official"; | ||||||
| 
 | 
 | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		Path[] classpath = mapProvider.getMapperPaths().stream() | 		Path[] classpath = mapProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new); | ||||||
| 				.map(File::toPath) |  | ||||||
| 				.toArray(Path[]::new); |  | ||||||
| 
 | 
 | ||||||
| 		Path input = jarProvider.getMergedJar().toPath(); | 		Path input = jarProvider.getMergedJar().toPath(); | ||||||
| 		Path outputMapped = mapProvider.getMappedJar().toPath(); | 		Path outputMapped = mapProvider.getMappedJar().toPath(); | ||||||
|  | @ -60,11 +56,7 @@ public class MapJarsTiny { | ||||||
| 
 | 
 | ||||||
| 			project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); | 			project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); | ||||||
| 
 | 
 | ||||||
| 			TinyRemapper remapper = TinyRemapper.newRemapper() | 			TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).renameInvalidLocals(true).rebuildSourceFilenames(true).build(); | ||||||
| 					.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)) |  | ||||||
| 					.renameInvalidLocals(true) |  | ||||||
| 					.rebuildSourceFilenames(true) |  | ||||||
| 					.build(); |  | ||||||
| 
 | 
 | ||||||
| 			try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { | 			try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { | ||||||
| 				outputConsumer.addNonClassFiles(input); | 				outputConsumer.addNonClassFiles(input); | ||||||
|  |  | ||||||
|  | @ -24,15 +24,13 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.JsonElement; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftLibraryProvider; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
|  | import com.google.gson.JsonElement; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | 
 | ||||||
| public class MinecraftVersionInfo { | public class MinecraftVersionInfo { | ||||||
| 	public List<Library> libraries; | 	public List<Library> libraries; | ||||||
| 	public Map<String, Downloads> downloads; | 	public Map<String, Downloads> downloads; | ||||||
|  | @ -93,14 +91,16 @@ public class MinecraftVersionInfo { | ||||||
| 				return ""; | 				return ""; | ||||||
| 			} else { | 			} else { | ||||||
| 				JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())); | 				JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())); | ||||||
| 				if(element == null){ | 
 | ||||||
|  | 				if (element == null) { | ||||||
| 					return ""; | 					return ""; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				return "-" + element.getAsString().replace("\"", ""); | 				return "-" + element.getAsString().replace("\"", ""); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public boolean isNative(){ | 		public boolean isNative() { | ||||||
| 			return getClassifier().contains("natives"); | 			return getClassifier().contains("natives"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -110,6 +110,7 @@ public class MinecraftVersionInfo { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			boolean success = false; | 			boolean success = false; | ||||||
|  | 
 | ||||||
| 			for (Rule rule : this.rules) { | 			for (Rule rule : this.rules) { | ||||||
| 				if (rule.os != null && rule.os.name != null) { | 				if (rule.os != null && rule.os.name != null) { | ||||||
| 					if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { | 					if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { | ||||||
|  | @ -119,6 +120,7 @@ public class MinecraftVersionInfo { | ||||||
| 					success = rule.action.equalsIgnoreCase("allow"); | 					success = rule.action.equalsIgnoreCase("allow"); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			return success; | 			return success; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -126,9 +128,11 @@ public class MinecraftVersionInfo { | ||||||
| 			if (artifact == null) { | 			if (artifact == null) { | ||||||
| 				artifact = new Artifact(name); | 				artifact = new Artifact(name); | ||||||
| 			} | 			} | ||||||
| 			if(natives != null){ | 
 | ||||||
|  | 			if (natives != null) { | ||||||
| 				JsonElement jsonElement = natives.get(OperatingSystem.getOS()); | 				JsonElement jsonElement = natives.get(OperatingSystem.getOS()); | ||||||
| 				if(jsonElement != null){ | 
 | ||||||
|  | 				if (jsonElement != null) { | ||||||
| 					return artifact.getArtifact(jsonElement.getAsString()); | 					return artifact.getArtifact(jsonElement.getAsString()); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -139,15 +143,17 @@ public class MinecraftVersionInfo { | ||||||
| 		private class Artifact { | 		private class Artifact { | ||||||
| 			private final String domain, name, version, classifier, ext; | 			private final String domain, name, version, classifier, ext; | ||||||
| 
 | 
 | ||||||
| 			public Artifact(String name) { | 			Artifact(String name) { | ||||||
| 				String[] splitedArtifact = name.split(":"); | 				String[] splitedArtifact = name.split(":"); | ||||||
| 				int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); | 				int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); | ||||||
|  | 
 | ||||||
| 				if (idx != -1) { | 				if (idx != -1) { | ||||||
| 					ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); | 					ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); | ||||||
| 					splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); | 					splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); | ||||||
| 				} else { | 				} else { | ||||||
| 					ext = "jar"; | 					ext = "jar"; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				this.domain = splitedArtifact[0]; | 				this.domain = splitedArtifact[0]; | ||||||
| 				this.name = splitedArtifact[1]; | 				this.name = splitedArtifact[1]; | ||||||
| 				this.version = splitedArtifact[2]; | 				this.version = splitedArtifact[2]; | ||||||
|  | @ -156,15 +162,19 @@ public class MinecraftVersionInfo { | ||||||
| 
 | 
 | ||||||
| 			public String getArtifact(String classifier) { | 			public String getArtifact(String classifier) { | ||||||
| 				String ret = domain + ":" + name + ":" + version; | 				String ret = domain + ":" + name + ":" + version; | ||||||
|  | 
 | ||||||
| 				if (classifier != null && classifier.indexOf('$') > -1) { | 				if (classifier != null && classifier.indexOf('$') > -1) { | ||||||
| 					classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); | 					classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				if (classifier != null) { | 				if (classifier != null) { | ||||||
| 					ret += ":" + classifier; | 					ret += ":" + classifier; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				if (!"jar".equals(ext)) { | 				if (!"jar".equals(ext)) { | ||||||
| 					ret += "@" + ext; | 					ret += "@" + ext; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				return ret; | 				return ret; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,15 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.GsonBuilder; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| import net.fabricmc.tinyremapper.TinyRemapper; |  | ||||||
| import org.objectweb.asm.commons.Remapper; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; |  | ||||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; |  | ||||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||||
|  | @ -41,86 +32,91 @@ import java.util.HashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||||
| 
 | 
 | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.GsonBuilder; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||||
|  | import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||||
|  | 
 | ||||||
| public final class MixinRefmapHelper { | public final class MixinRefmapHelper { | ||||||
|     private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | 	private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | ||||||
| 
 | 
 | ||||||
|     private MixinRefmapHelper() { | 	private MixinRefmapHelper() { } | ||||||
| 
 | 
 | ||||||
|     } | 	public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) { | ||||||
|  | 		File output = outputPath.toFile(); | ||||||
|  | 		Set<String> mixinFilenames = findMixins(output, true); | ||||||
| 
 | 
 | ||||||
|     public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) { | 		if (mixinFilenames.size() > 0) { | ||||||
|         File output = outputPath.toFile(); | 			return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { | ||||||
|         Set<String> mixinFilenames = findMixins(output, true); | 				@Override | ||||||
|  | 				protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||||
|  | 					JsonObject json = GSON.fromJson(input, JsonObject.class); | ||||||
| 
 | 
 | ||||||
|         if (mixinFilenames.size() > 0) { | 					if (!json.has("refmap")) { | ||||||
|             return ZipUtil.transformEntries( | 						json.addProperty("refmap", filename); | ||||||
|                     output, | 					} | ||||||
|                     mixinFilenames.stream() |  | ||||||
|                             .map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { |  | ||||||
|                                 @Override |  | ||||||
|                                 protected String transform(ZipEntry zipEntry, String input) throws IOException { |  | ||||||
|                                     JsonObject json = GSON.fromJson(input, JsonObject.class); |  | ||||||
|                                     if (!json.has("refmap")) { |  | ||||||
|                                         json.addProperty("refmap", filename); |  | ||||||
|                                     } |  | ||||||
|                                     if (!json.has("minVersion") && mixinVersion != null) { |  | ||||||
|                                         json.addProperty("minVersion", mixinVersion); |  | ||||||
|                                     } |  | ||||||
|                                     return GSON.toJson(json); |  | ||||||
|                                 } |  | ||||||
|                             })).toArray(ZipEntryTransformerEntry[]::new) |  | ||||||
|             ); |  | ||||||
|         } else { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { | 					if (!json.has("minVersion") && mixinVersion != null) { | ||||||
|         // first, identify all of the mixin files | 						json.addProperty("minVersion", mixinVersion); | ||||||
|         Set<String> mixinFilename = new HashSet<>(); | 					} | ||||||
|         // TODO: this is a lovely hack |  | ||||||
|         ZipUtil.iterate(output, (stream, entry) -> { |  | ||||||
|             if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { |  | ||||||
|                 // JSON file in root directory |  | ||||||
|                 try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { |  | ||||||
|                     JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); |  | ||||||
| 
 | 
 | ||||||
|                     if (json != null) { | 					return GSON.toJson(json); | ||||||
|                         boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); | 				} | ||||||
|                         boolean hasClient = json.has("client") && json.get("client").isJsonArray(); | 			})).toArray(ZipEntryTransformerEntry[]::new)); | ||||||
|                         boolean hasServer = json.has("server") && json.get("server").isJsonArray(); | 		} else { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|                         if (json.has("package") && (hasMixins || hasClient || hasServer)) { | 	private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { | ||||||
|                             if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { | 		// first, identify all of the mixin files | ||||||
|                                 mixinFilename.add(entry.getName()); | 		Set<String> mixinFilename = new HashSet<>(); | ||||||
|                             } | 		// TODO: this is a lovely hack | ||||||
|                         } | 		ZipUtil.iterate(output, (stream, entry) -> { | ||||||
|                     } | 			if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||||
|                 } catch (Exception e) { | 				// JSON file in root directory | ||||||
|                     // ... | 				try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||||
|                 } | 					JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         return mixinFilename; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static Set<String> findRefmaps(File output) { | 					if (json != null) { | ||||||
|         // first, identify all of the mixin refmaps | 						boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); | ||||||
|         Set<String> mixinRefmapFilenames = new HashSet<>(); | 						boolean hasClient = json.has("client") && json.get("client").isJsonArray(); | ||||||
|         // TODO: this is also a lovely hack | 						boolean hasServer = json.has("server") && json.get("server").isJsonArray(); | ||||||
|         ZipUtil.iterate(output, (stream, entry) -> { | 
 | ||||||
|             if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | 						if (json.has("package") && (hasMixins || hasClient || hasServer)) { | ||||||
|                 // JSON file in root directory | 							if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { | ||||||
|                 try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | 								mixinFilename.add(entry.getName()); | ||||||
|                     JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | 							} | ||||||
|                     if (json != null && json.has("refmap")) { | 						} | ||||||
|                         mixinRefmapFilenames.add(json.get("refmap").getAsString()); | 					} | ||||||
|                     } | 				} catch (Exception e) { | ||||||
|                 } catch (Exception e) { | 					// ... | ||||||
|                     // ... | 				} | ||||||
|                 } | 			} | ||||||
|             } | 		}); | ||||||
|         }); | 		return mixinFilename; | ||||||
|         return mixinRefmapFilenames; | 	} | ||||||
|     } | 
 | ||||||
|  | 	private static Set<String> findRefmaps(File output) { | ||||||
|  | 		// first, identify all of the mixin refmaps | ||||||
|  | 		Set<String> mixinRefmapFilenames = new HashSet<>(); | ||||||
|  | 		// TODO: this is also a lovely hack | ||||||
|  | 		ZipUtil.iterate(output, (stream, entry) -> { | ||||||
|  | 			if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||||
|  | 				// JSON file in root directory | ||||||
|  | 				try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||||
|  | 					JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||||
|  | 
 | ||||||
|  | 					if (json != null && json.has("refmap")) { | ||||||
|  | 						mixinRefmapFilenames.add(json.get("refmap").getAsString()); | ||||||
|  | 					} | ||||||
|  | 				} catch (Exception e) { | ||||||
|  | 					// ... | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		return mixinRefmapFilenames; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,7 +24,11 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.concurrent.atomic.AtomicBoolean; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  | 
 | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.artifacts.Configuration; | import org.gradle.api.artifacts.Configuration; | ||||||
| import org.gradle.api.artifacts.Dependency; | import org.gradle.api.artifacts.Dependency; | ||||||
|  | @ -40,10 +44,7 @@ import org.gradle.api.logging.Logger; | ||||||
| import org.gradle.jvm.JvmLibrary; | import org.gradle.jvm.JvmLibrary; | ||||||
| import org.gradle.language.base.artifact.SourcesArtifact; | import org.gradle.language.base.artifact.SourcesArtifact; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.concurrent.atomic.AtomicBoolean; |  | ||||||
| import java.util.function.Consumer; |  | ||||||
| 
 | 
 | ||||||
| public class ModCompileRemapper { | public class ModCompileRemapper { | ||||||
| 	public static void remapDependencies(Project project, String mappingsPrefix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) { | 	public static void remapDependencies(Project project, String mappingsPrefix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) { | ||||||
|  | @ -93,7 +94,7 @@ public class ModCompileRemapper { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json | 	 * Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json. | ||||||
| 	 */ | 	 */ | ||||||
| 	private static boolean isFabricMod(Project project, Logger logger, ResolvedArtifact artifact, String notation) { | 	private static boolean isFabricMod(Project project, Logger logger, ResolvedArtifact artifact, String notation) { | ||||||
| 		File input = artifact.getFile(); | 		File input = artifact.getFile(); | ||||||
|  | @ -112,15 +113,18 @@ public class ModCompileRemapper { | ||||||
| 		project.getLogger().info(":providing " + notation); | 		project.getLogger().info(":providing " + notation); | ||||||
| 		DependencyHandler dependencies = project.getDependencies(); | 		DependencyHandler dependencies = project.getDependencies(); | ||||||
| 		Dependency dep = dependencies.module(notation); | 		Dependency dep = dependencies.module(notation); | ||||||
|  | 
 | ||||||
| 		if (dep instanceof ModuleDependency) { | 		if (dep instanceof ModuleDependency) { | ||||||
| 			((ModuleDependency) dep).setTransitive(false); | 			((ModuleDependency) dep).setTransitive(false); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		dependencies.add(regularCompile.getName(), dep); | 		dependencies.add(regularCompile.getName(), dep); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) { | 	private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) { | ||||||
| 		File input = artifact.getFile(); | 		File input = artifact.getFile(); | ||||||
| 		File output = new File(modStore, remappedFilename + ".jar"); | 		File output = new File(modStore, remappedFilename + ".jar"); | ||||||
|  | 
 | ||||||
| 		if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) { | 		if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) { | ||||||
| 			//If the output doesn't exist, or appears to be outdated compared to the input we'll remap it | 			//If the output doesn't exist, or appears to be outdated compared to the input we'll remap it | ||||||
| 			try { | 			try { | ||||||
|  | @ -129,7 +133,7 @@ public class ModCompileRemapper { | ||||||
| 				throw new RuntimeException("Failed to remap mod", e); | 				throw new RuntimeException("Failed to remap mod", e); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (!output.exists()){ | 			if (!output.exists()) { | ||||||
| 				throw new RuntimeException("Failed to remap mod"); | 				throw new RuntimeException("Failed to remap mod"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -142,10 +146,10 @@ public class ModCompileRemapper { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) { | 	private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) { | ||||||
| 		@SuppressWarnings ("unchecked") | 		@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()// | ||||||
| 		ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()// |  | ||||||
| 				.forComponents(artifact.getId().getComponentIdentifier())// | 				.forComponents(artifact.getId().getComponentIdentifier())// | ||||||
| 				.withArtifacts(JvmLibrary.class, SourcesArtifact.class); | 				.withArtifacts(JvmLibrary.class, SourcesArtifact.class); | ||||||
|  | 
 | ||||||
| 		for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { | 		for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { | ||||||
| 			for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { | 			for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { | ||||||
| 				if (srcArtifact instanceof ResolvedArtifactResult) { | 				if (srcArtifact instanceof ResolvedArtifactResult) { | ||||||
|  | @ -153,6 +157,7 @@ public class ModCompileRemapper { | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,23 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.JsonArray; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; |  | ||||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; |  | ||||||
| import net.fabricmc.tinyremapper.TinyRemapper; |  | ||||||
| import org.apache.commons.io.IOUtils; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.artifacts.Configuration; |  | ||||||
| import org.gradle.internal.impldep.aQute.lib.strings.Strings; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; |  | ||||||
| import org.zeroturnaround.zip.commons.FileUtils; |  | ||||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; |  | ||||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
|  | @ -54,18 +37,39 @@ import java.util.jar.JarEntry; | ||||||
| import java.util.jar.JarFile; | import java.util.jar.JarFile; | ||||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||||
| 
 | 
 | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.JsonArray; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import org.apache.commons.io.IOUtils; | ||||||
|  | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.zeroturnaround.zip.commons.FileUtils; | ||||||
|  | import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||||
|  | import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.artifacts.Configuration; | ||||||
|  | import org.gradle.internal.impldep.aQute.lib.strings.Strings; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||||
|  | import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||||
|  | import net.fabricmc.tinyremapper.TinyRemapper; | ||||||
|  | 
 | ||||||
| public class ModProcessor { | public class ModProcessor { | ||||||
| 	private static final Gson GSON = new Gson(); | 	private static final Gson GSON = new Gson(); | ||||||
| 
 | 
 | ||||||
| 	public static void processMod(File input, File output, Project project, Configuration config) throws IOException { | 	public static void processMod(File input, File output, Project project, Configuration config) throws IOException { | ||||||
| 		if(output.exists()){ | 		if (output.exists()) { | ||||||
| 			output.delete(); | 			output.delete(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		remapJar(input, output, project); | 		remapJar(input, output, project); | ||||||
|  | 
 | ||||||
| 		//Enable this if you want your nested jars to be extracted, this will extract **all** jars | 		//Enable this if you want your nested jars to be extracted, this will extract **all** jars | ||||||
| 		if(project.getExtensions().getByType(LoomGradleExtension.class).extractJars){ | 		if (project.getExtensions().getByType(LoomGradleExtension.class).extractJars) { | ||||||
| 			handleNestedJars(input, project, config); | 			handleNestedJars(input, project, config); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		//Always strip the nested jars | 		//Always strip the nested jars | ||||||
| 		stripNestedJars(output); | 		stripNestedJars(output); | ||||||
| 	} | 	} | ||||||
|  | @ -77,15 +81,20 @@ public class ModProcessor { | ||||||
| 	private static void handleNestedJars(File input, Project project, Configuration config) throws IOException { | 	private static void handleNestedJars(File input, Project project, Configuration config) throws IOException { | ||||||
| 		JarFile jarFile = new JarFile(input); | 		JarFile jarFile = new JarFile(input); | ||||||
| 		JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json"); | 		JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json"); | ||||||
| 		if(modJsonEntry == null){ | 
 | ||||||
|  | 		if (modJsonEntry == null) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		try(InputStream inputStream = jarFile.getInputStream(modJsonEntry)){ | 
 | ||||||
|  | 		try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) { | ||||||
| 			JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class); | 			JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class); | ||||||
| 			if(json == null || !json.has("jars")){ | 
 | ||||||
|  | 			if (json == null || !json.has("jars")) { | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			JsonArray jsonArray = json.getAsJsonArray("jars"); | 			JsonArray jsonArray = json.getAsJsonArray("jars"); | ||||||
|  | 
 | ||||||
| 			for (int i = 0; i < jsonArray.size(); i++) { | 			for (int i = 0; i < jsonArray.size(); i++) { | ||||||
| 				JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); | 				JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); | ||||||
| 				String fileName = jsonObject.get("file").getAsString(); | 				String fileName = jsonObject.get("file").getAsString(); | ||||||
|  | @ -99,19 +108,22 @@ public class ModProcessor { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
| 		JarEntry entry = parentJar.getJarEntry(fileName); | 		JarEntry entry = parentJar.getJarEntry(fileName); | ||||||
| 		if(entry == null){ | 
 | ||||||
|  | 		if (entry == null) { | ||||||
| 			throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName())); | 			throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName())); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | 		File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | ||||||
| 		try(InputStream jarStream = parentJar.getInputStream(entry)) { | 
 | ||||||
|  | 		try (InputStream jarStream = parentJar.getInputStream(entry)) { | ||||||
| 			FileUtils.copy(jarStream, nestedFile); | 			FileUtils.copy(jarStream, nestedFile); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | 		File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | ||||||
| 
 | 
 | ||||||
| 		processMod(nestedFile, remappedFile, project, config); | 		processMod(nestedFile, remappedFile, project, config); | ||||||
| 
 | 
 | ||||||
| 		if(!remappedFile.exists()){ | 		if (!remappedFile.exists()) { | ||||||
| 			throw new RuntimeException("Failed to find processed nested jar"); | 			throw new RuntimeException("Failed to find processed nested jar"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -119,7 +131,7 @@ public class ModProcessor { | ||||||
| 		project.getDependencies().add(config.getName(), project.files(remappedFile)); | 		project.getDependencies().add(config.getName(), project.files(remappedFile)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void stripNestedJars(File file){ | 	private static void stripNestedJars(File file) { | ||||||
| 		//Strip out all contained jar info as we dont want loader to try and load the jars contained in dev. | 		//Strip out all contained jar info as we dont want loader to try and load the jars contained in dev. | ||||||
| 		ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { | 		ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { | ||||||
| 			@Override | 			@Override | ||||||
|  | @ -143,29 +155,22 @@ public class ModProcessor { | ||||||
| 		Path mappings = mappingsFile.toPath(); | 		Path mappings = mappingsFile.toPath(); | ||||||
| 		Path inputPath = input.getAbsoluteFile().toPath(); | 		Path inputPath = input.getAbsoluteFile().toPath(); | ||||||
| 		Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath(); | 		Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath(); | ||||||
| 		Path[] mcDeps = mappedProvider.getMapperPaths().stream() | 		Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new); | ||||||
| 			.map(File::toPath) |  | ||||||
| 			.toArray(Path[]::new); |  | ||||||
| 		Set<Path> modCompiles = new HashSet<>(); | 		Set<Path> modCompiles = new HashSet<>(); | ||||||
| 		for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { |  | ||||||
| 			project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream() |  | ||||||
| 					.filter((f) -> !f.equals(input)) |  | ||||||
| 					.map(p -> { |  | ||||||
| 						if (p.equals(input)) { |  | ||||||
| 							return inputPath; |  | ||||||
| 						} else { |  | ||||||
| 							return p.toPath(); |  | ||||||
| 						} |  | ||||||
| 					}) |  | ||||||
| 					.forEach(modCompiles::add); |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
|  | 		for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | ||||||
|  | 			project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream().filter((f) -> !f.equals(input)).map(p -> { | ||||||
|  | 				if (p.equals(input)) { | ||||||
|  | 					return inputPath; | ||||||
|  | 				} else { | ||||||
|  | 					return p.toPath(); | ||||||
|  | 				} | ||||||
|  | 			}).forEach(modCompiles::add); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")"); | 		project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")"); | ||||||
| 
 | 
 | ||||||
| 		TinyRemapper remapper = TinyRemapper.newRemapper() | 		TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).build(); | ||||||
| 			.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)) |  | ||||||
| 			.build(); |  | ||||||
| 
 | 
 | ||||||
| 		try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) { | 		try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) { | ||||||
| 			outputConsumer.addNonClassFiles(inputPath); | 			outputConsumer.addNonClassFiles(inputPath); | ||||||
|  | @ -178,12 +183,12 @@ public class ModProcessor { | ||||||
| 			remapper.finish(); | 			remapper.finish(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if(!output.exists()){ | 		if (!output.exists()) { | ||||||
| 			throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath()); | 			throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath()); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static void readInstallerJson(File file, Project project){ | 	static void readInstallerJson(File file, Project project) { | ||||||
| 		try { | 		try { | ||||||
| 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 			String launchMethod = extension.getLoaderLaunchMethod(); | 			String launchMethod = extension.getLoaderLaunchMethod(); | ||||||
|  | @ -193,8 +198,10 @@ public class ModProcessor { | ||||||
| 
 | 
 | ||||||
| 			try (JarFile jarFile = new JarFile(file)) { | 			try (JarFile jarFile = new JarFile(file)) { | ||||||
| 				ZipEntry entry = null; | 				ZipEntry entry = null; | ||||||
|  | 
 | ||||||
| 				if (!launchMethod.isEmpty()) { | 				if (!launchMethod.isEmpty()) { | ||||||
| 					entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json"); | 					entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json"); | ||||||
|  | 
 | ||||||
| 					if (entry == null) { | 					if (entry == null) { | ||||||
| 						project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back"); | 						project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back"); | ||||||
| 					} | 					} | ||||||
|  | @ -203,6 +210,7 @@ public class ModProcessor { | ||||||
| 				if (entry == null) { | 				if (entry == null) { | ||||||
| 					entry = jarFile.getEntry("fabric-installer.json"); | 					entry = jarFile.getEntry("fabric-installer.json"); | ||||||
| 					priority++; | 					priority++; | ||||||
|  | 
 | ||||||
| 					if (entry == null) { | 					if (entry == null) { | ||||||
| 						return; | 						return; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -24,28 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.GsonBuilder; |  | ||||||
| import com.google.gson.JsonArray; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| 
 |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.task.RemapJarTask; |  | ||||||
| 
 |  | ||||||
| import org.apache.commons.io.FileUtils; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.api.Task; |  | ||||||
| import org.gradle.api.artifacts.Configuration; |  | ||||||
| import org.gradle.api.artifacts.Dependency; |  | ||||||
| import org.gradle.api.artifacts.DependencySet; |  | ||||||
| import org.gradle.api.artifacts.ProjectDependency; |  | ||||||
| import org.gradle.api.tasks.bundling.AbstractArchiveTask; |  | ||||||
| import org.zeroturnaround.zip.FileSource; |  | ||||||
| import org.zeroturnaround.zip.ZipEntrySource; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; |  | ||||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; |  | ||||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
|  | @ -56,8 +34,28 @@ import java.util.Locale; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||||
| 
 | 
 | ||||||
| public class NestedJars { | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.GsonBuilder; | ||||||
|  | import com.google.gson.JsonArray; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
|  | import org.zeroturnaround.zip.FileSource; | ||||||
|  | import org.zeroturnaround.zip.ZipEntrySource; | ||||||
|  | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||||
|  | import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.Task; | ||||||
|  | import org.gradle.api.artifacts.Configuration; | ||||||
|  | import org.gradle.api.artifacts.Dependency; | ||||||
|  | import org.gradle.api.artifacts.DependencySet; | ||||||
|  | import org.gradle.api.artifacts.ProjectDependency; | ||||||
|  | import org.gradle.api.tasks.bundling.AbstractArchiveTask; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.task.RemapJarTask; | ||||||
|  | 
 | ||||||
|  | public class NestedJars { | ||||||
| 	private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | 	private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | ||||||
| 
 | 
 | ||||||
| 	public static boolean addNestedJars(Project project, Path modJarPath) { | 	public static boolean addNestedJars(Project project, Path modJarPath) { | ||||||
|  | @ -74,6 +72,7 @@ public class NestedJars { | ||||||
| 			protected String transform(ZipEntry zipEntry, String input) throws IOException { | 			protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||||
| 				JsonObject json = GSON.fromJson(input, JsonObject.class); | 				JsonObject json = GSON.fromJson(input, JsonObject.class); | ||||||
| 				JsonArray nestedJars = json.getAsJsonArray("jars"); | 				JsonArray nestedJars = json.getAsJsonArray("jars"); | ||||||
|  | 
 | ||||||
| 				if (nestedJars == null || !json.has("jars")) { | 				if (nestedJars == null || !json.has("jars")) { | ||||||
| 					nestedJars = new JsonArray(); | 					nestedJars = new JsonArray(); | ||||||
| 				} | 				} | ||||||
|  | @ -96,6 +95,7 @@ public class NestedJars { | ||||||
| 
 | 
 | ||||||
| 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | ||||||
| 		DependencySet dependencies = configuration.getDependencies(); | 		DependencySet dependencies = configuration.getDependencies(); | ||||||
|  | 
 | ||||||
| 		for (Dependency dependency : dependencies) { | 		for (Dependency dependency : dependencies) { | ||||||
| 			if (dependency instanceof ProjectDependency) { | 			if (dependency instanceof ProjectDependency) { | ||||||
| 				ProjectDependency projectDependency = (ProjectDependency) dependency; | 				ProjectDependency projectDependency = (ProjectDependency) dependency; | ||||||
|  | @ -116,27 +116,32 @@ public class NestedJars { | ||||||
| 				fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project)); | 				fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project)); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		for (File file : fileList) { | 		for (File file : fileList) { | ||||||
| 			if (!file.exists()) { | 			if (!file.exists()) { | ||||||
| 				throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); | 				throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			if (file.isDirectory() || !file.getName().endsWith(".jar")) { | 			if (file.isDirectory() || !file.getName().endsWith(".jar")) { | ||||||
| 				throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); | 				throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return fileList; | 		return fileList; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//Looks for any deps that require a sub project to be built first | 	//Looks for any deps that require a sub project to be built first | ||||||
| 	public static List<RemapJarTask> getRequiredTasks(Project project){ | 	public static List<RemapJarTask> getRequiredTasks(Project project) { | ||||||
| 		List<RemapJarTask> remapTasks = new ArrayList<>(); | 		List<RemapJarTask> remapTasks = new ArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | ||||||
| 		DependencySet dependencies = configuration.getDependencies(); | 		DependencySet dependencies = configuration.getDependencies(); | ||||||
|  | 
 | ||||||
| 		for (Dependency dependency : dependencies) { | 		for (Dependency dependency : dependencies) { | ||||||
| 			if (dependency instanceof ProjectDependency) { | 			if (dependency instanceof ProjectDependency) { | ||||||
| 				ProjectDependency projectDependency = (ProjectDependency) dependency; | 				ProjectDependency projectDependency = (ProjectDependency) dependency; | ||||||
| 				Project dependencyProject = projectDependency.getDependencyProject(); | 				Project dependencyProject = projectDependency.getDependencyProject(); | ||||||
|  | 
 | ||||||
| 				for (Task task : dependencyProject.getTasksByName("remapJar", false)) { | 				for (Task task : dependencyProject.getTasksByName("remapJar", false)) { | ||||||
| 					if (task instanceof RemapJarTask) { | 					if (task instanceof RemapJarTask) { | ||||||
| 						remapTasks.add((RemapJarTask) task); | 						remapTasks.add((RemapJarTask) task); | ||||||
|  | @ -144,29 +149,36 @@ public class NestedJars { | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return remapTasks; | 		return remapTasks; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library | 	//This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library | ||||||
| 	private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project){ | 	private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project) { | ||||||
| 		List<File> fileList = new ArrayList<>(); | 		List<File> fileList = new ArrayList<>(); | ||||||
| 		for(File file : files){ | 
 | ||||||
|  | 		for (File file : files) { | ||||||
| 			//A lib that doesnt have a mod.json, we turn it into a fake mod | 			//A lib that doesnt have a mod.json, we turn it into a fake mod | ||||||
| 			if(!ZipUtil.containsEntry(file, "fabric.mod.json")){ | 			if (!ZipUtil.containsEntry(file, "fabric.mod.json")) { | ||||||
| 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 				File tempDir = new File(extension.getUserCache(), "temp/modprocessing"); | 				File tempDir = new File(extension.getUserCache(), "temp/modprocessing"); | ||||||
| 				if(!tempDir.exists()){ | 
 | ||||||
|  | 				if (!tempDir.exists()) { | ||||||
| 					tempDir.mkdirs(); | 					tempDir.mkdirs(); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				File tempFile = new File(tempDir, file.getName()); | 				File tempFile = new File(tempDir, file.getName()); | ||||||
| 				if(tempFile.exists()){ | 
 | ||||||
|  | 				if (tempFile.exists()) { | ||||||
| 					tempFile.delete(); | 					tempFile.delete(); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				try { | 				try { | ||||||
| 					FileUtils.copyFile(file, tempFile); | 					FileUtils.copyFile(file, tempFile); | ||||||
| 				} catch (IOException e) { | 				} catch (IOException e) { | ||||||
| 					throw new RuntimeException("Failed to copy file", e); | 					throw new RuntimeException("Failed to copy file", e); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes()); | 				ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes()); | ||||||
| 				fileList.add(tempFile); | 				fileList.add(tempFile); | ||||||
| 			} else { | 			} else { | ||||||
|  | @ -174,11 +186,12 @@ public class NestedJars { | ||||||
| 				fileList.add(file); | 				fileList.add(file); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return fileList; | 		return fileList; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//Generates a barebones mod for a dependency | 	//Generates a barebones mod for a dependency | ||||||
| 	private static String getMod(Dependency dependency){ | 	private static String getMod(Dependency dependency) { | ||||||
| 		JsonObject jsonObject = new JsonObject(); | 		JsonObject jsonObject = new JsonObject(); | ||||||
| 		jsonObject.addProperty("schemaVersion", 1); | 		jsonObject.addProperty("schemaVersion", 1); | ||||||
| 		jsonObject.addProperty("id", (dependency.getGroup().replaceAll("\\.", "_") + "_" + dependency.getName()).toLowerCase(Locale.ENGLISH)); | 		jsonObject.addProperty("id", (dependency.getGroup().replaceAll("\\.", "_") + "_" + dependency.getName()).toLowerCase(Locale.ENGLISH)); | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ package net.fabricmc.loom.util; | ||||||
| public class OperatingSystem { | public class OperatingSystem { | ||||||
| 	public static String getOS() { | 	public static String getOS() { | ||||||
| 		String osName = System.getProperty("os.name").toLowerCase(); | 		String osName = System.getProperty("os.name").toLowerCase(); | ||||||
|  | 
 | ||||||
| 		if (osName.contains("win")) { | 		if (osName.contains("win")) { | ||||||
| 			return "windows"; | 			return "windows"; | ||||||
| 		} else if (osName.contains("mac")) { | 		} else if (osName.contains("mac")) { | ||||||
|  |  | ||||||
|  | @ -27,43 +27,43 @@ package net.fabricmc.loom.util; | ||||||
| import org.gradle.api.artifacts.ConfigurationContainer; | import org.gradle.api.artifacts.ConfigurationContainer; | ||||||
| 
 | 
 | ||||||
| public class RemappedConfigurationEntry { | public class RemappedConfigurationEntry { | ||||||
|     private final String sourceConfiguration; | 	private final String sourceConfiguration; | ||||||
|     private final String targetConfiguration; | 	private final String targetConfiguration; | ||||||
|     private final String mavenScope; | 	private final String mavenScope; | ||||||
|     private final boolean isOnModCompileClasspath; | 	private final boolean isOnModCompileClasspath; | ||||||
| 
 | 
 | ||||||
|     public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { | 	public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { | ||||||
|         this.sourceConfiguration = sourceConfiguration; | 		this.sourceConfiguration = sourceConfiguration; | ||||||
|         this.targetConfiguration = targetConfiguration; | 		this.targetConfiguration = targetConfiguration; | ||||||
|         this.isOnModCompileClasspath = isOnModCompileClasspath; | 		this.isOnModCompileClasspath = isOnModCompileClasspath; | ||||||
|         this.mavenScope = mavenScope; | 		this.mavenScope = mavenScope; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public String getMavenScope() { | 	public String getMavenScope() { | ||||||
|         return mavenScope; | 		return mavenScope; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public boolean hasMavenScope() { | 	public boolean hasMavenScope() { | ||||||
|         return mavenScope != null && !mavenScope.isEmpty(); | 		return mavenScope != null && !mavenScope.isEmpty(); | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public boolean isOnModCompileClasspath() { | 	public boolean isOnModCompileClasspath() { | ||||||
|         return isOnModCompileClasspath; | 		return isOnModCompileClasspath; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public String getSourceConfiguration() { | 	public String getSourceConfiguration() { | ||||||
|         return sourceConfiguration; | 		return sourceConfiguration; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public String getRemappedConfiguration() { | 	public String getRemappedConfiguration() { | ||||||
|         return sourceConfiguration + "Mapped"; | 		return sourceConfiguration + "Mapped"; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public String getTargetConfiguration(ConfigurationContainer container) { | 	public String getTargetConfiguration(ConfigurationContainer container) { | ||||||
|         if (container.findByName(targetConfiguration) == null) { | 		if (container.findByName(targetConfiguration) == null) { | ||||||
|             return "compile"; | 			return "compile"; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         return targetConfiguration; | 		return targetConfiguration; | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,21 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.common.base.Strings; |  | ||||||
| import com.google.common.collect.ImmutableList; |  | ||||||
| import com.google.common.collect.ImmutableMap; |  | ||||||
| import com.google.gson.JsonElement; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftProvider; |  | ||||||
| import org.apache.commons.io.IOUtils; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.w3c.dom.Document; |  | ||||||
| import org.w3c.dom.Element; |  | ||||||
| import org.w3c.dom.Node; |  | ||||||
| 
 |  | ||||||
| import javax.xml.parsers.ParserConfigurationException; |  | ||||||
| import javax.xml.transform.TransformerException; |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
|  | @ -47,6 +32,23 @@ import java.util.List; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
|  | import javax.xml.parsers.ParserConfigurationException; | ||||||
|  | import javax.xml.transform.TransformerException; | ||||||
|  | 
 | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | import com.google.common.collect.ImmutableList; | ||||||
|  | import com.google.common.collect.ImmutableMap; | ||||||
|  | import com.google.gson.JsonElement; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import org.apache.commons.io.IOUtils; | ||||||
|  | import org.w3c.dom.Document; | ||||||
|  | import org.w3c.dom.Element; | ||||||
|  | import org.w3c.dom.Node; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftProvider; | ||||||
|  | 
 | ||||||
| public class RunConfig { | public class RunConfig { | ||||||
| 	public String configName; | 	public String configName; | ||||||
| 	public String projectName; | 	public String projectName; | ||||||
|  | @ -70,19 +72,23 @@ public class RunConfig { | ||||||
| 		if (!Strings.isNullOrEmpty(programArgs)) { | 		if (!Strings.isNullOrEmpty(programArgs)) { | ||||||
| 			this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); | 			this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return root; | 		return root; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public Element addXml(Node parent, String name, Map<String, String> values) { | 	public Element addXml(Node parent, String name, Map<String, String> values) { | ||||||
| 		Document doc = parent.getOwnerDocument(); | 		Document doc = parent.getOwnerDocument(); | ||||||
|  | 
 | ||||||
| 		if (doc == null) { | 		if (doc == null) { | ||||||
| 			doc = (Document) parent; | 			doc = (Document) parent; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		Element e = doc.createElement(name); | 		Element e = doc.createElement(name); | ||||||
|  | 
 | ||||||
| 		for (Map.Entry<String, String> entry : values.entrySet()) { | 		for (Map.Entry<String, String> entry : values.entrySet()) { | ||||||
| 			e.setAttribute(entry.getKey(), entry.getValue()); | 			e.setAttribute(entry.getKey(), entry.getValue()); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		parent.appendChild(e); | 		parent.appendChild(e); | ||||||
| 		return e; | 		return e; | ||||||
| 	} | 	} | ||||||
|  | @ -90,29 +96,32 @@ public class RunConfig { | ||||||
| 	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { | 	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { | ||||||
| 		runConfig.projectName = project.getName(); | 		runConfig.projectName = project.getName(); | ||||||
| 		runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | 		runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | ||||||
| 		runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath()  + "\""; | 		runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath() + "\""; | ||||||
| 
 | 
 | ||||||
| 		switch (extension.getLoaderLaunchMethod()) { | 		switch (extension.getLoaderLaunchMethod()) { | ||||||
| 			case "launchwrapper": | 		case "launchwrapper": | ||||||
| 				runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; | 			runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; | ||||||
| 				runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER); | 			runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER); | ||||||
| 				break; | 			break; | ||||||
| 			default: | 		default: | ||||||
| 				runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT); | 			runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT); | ||||||
| 				runConfig.programArgs = ""; | 			runConfig.programArgs = ""; | ||||||
| 				break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// if installer.json found... | 		// if installer.json found... | ||||||
| 		JsonObject installerJson = extension.getInstallerJson(); | 		JsonObject installerJson = extension.getInstallerJson(); | ||||||
|  | 
 | ||||||
| 		if (installerJson != null) { | 		if (installerJson != null) { | ||||||
| 			List<String> sideKeys = ImmutableList.of(mode, "common"); | 			List<String> sideKeys = ImmutableList.of(mode, "common"); | ||||||
| 
 | 
 | ||||||
| 			// copy main class | 			// copy main class | ||||||
| 			if (installerJson.has("mainClass")) { | 			if (installerJson.has("mainClass")) { | ||||||
| 				JsonElement mainClassJson = installerJson.get("mainClass"); | 				JsonElement mainClassJson = installerJson.get("mainClass"); | ||||||
|  | 
 | ||||||
| 				if (mainClassJson.isJsonObject()) { | 				if (mainClassJson.isJsonObject()) { | ||||||
| 					JsonObject mainClassesJson = mainClassJson.getAsJsonObject(); | 					JsonObject mainClassesJson = mainClassJson.getAsJsonObject(); | ||||||
|  | 
 | ||||||
| 					for (String s : sideKeys) { | 					for (String s : sideKeys) { | ||||||
| 						if (mainClassesJson.has(s)) { | 						if (mainClassesJson.has(s)) { | ||||||
| 							runConfig.mainClass = mainClassesJson.get(s).getAsString(); | 							runConfig.mainClass = mainClassesJson.get(s).getAsString(); | ||||||
|  | @ -127,9 +136,11 @@ public class RunConfig { | ||||||
| 			// copy launchwrapper tweakers | 			// copy launchwrapper tweakers | ||||||
| 			if (installerJson.has("launchwrapper")) { | 			if (installerJson.has("launchwrapper")) { | ||||||
| 				JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper"); | 				JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper"); | ||||||
|  | 
 | ||||||
| 				if (launchwrapperJson.has("tweakers")) { | 				if (launchwrapperJson.has("tweakers")) { | ||||||
| 					JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers"); | 					JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers"); | ||||||
| 					StringBuilder builder = new StringBuilder(); | 					StringBuilder builder = new StringBuilder(); | ||||||
|  | 
 | ||||||
| 					for (String s : sideKeys) { | 					for (String s : sideKeys) { | ||||||
| 						if (tweakersJson.has(s)) { | 						if (tweakersJson.has(s)) { | ||||||
| 							for (JsonElement element : tweakersJson.getAsJsonArray(s)) { | 							for (JsonElement element : tweakersJson.getAsJsonArray(s)) { | ||||||
|  | @ -137,15 +148,16 @@ public class RunConfig { | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  | 
 | ||||||
| 					runConfig.programArgs += builder.toString(); | 					runConfig.programArgs += builder.toString(); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static RunConfig clientRunConfig(Project project){ | 	public static RunConfig clientRunConfig(Project project) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MinecraftProvider minecraftProvider =  extension.getMinecraftProvider(); | 		MinecraftProvider minecraftProvider = extension.getMinecraftProvider(); | ||||||
| 		MinecraftVersionInfo minecraftVersionInfo = minecraftProvider.versionInfo; | 		MinecraftVersionInfo minecraftVersionInfo = minecraftProvider.versionInfo; | ||||||
| 
 | 
 | ||||||
| 		RunConfig ideaClient = new RunConfig(); | 		RunConfig ideaClient = new RunConfig(); | ||||||
|  | @ -157,7 +169,7 @@ public class RunConfig { | ||||||
| 		return ideaClient; | 		return ideaClient; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static RunConfig serverRunConfig(Project project){ | 	public static RunConfig serverRunConfig(Project project) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
| 		RunConfig ideaServer = new RunConfig(); | 		RunConfig ideaServer = new RunConfig(); | ||||||
|  | @ -169,6 +181,7 @@ public class RunConfig { | ||||||
| 
 | 
 | ||||||
| 	public String fromDummy(String dummy) throws IOException { | 	public String fromDummy(String dummy) throws IOException { | ||||||
| 		String dummyConfig; | 		String dummyConfig; | ||||||
|  | 
 | ||||||
| 		try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) { | 		try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) { | ||||||
| 			dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8); | 			dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8); | ||||||
| 		} | 		} | ||||||
|  | @ -182,10 +195,11 @@ public class RunConfig { | ||||||
| 		return dummyConfig; | 		return dummyConfig; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static String getOSClientJVMArgs(){ | 	public static String getOSClientJVMArgs() { | ||||||
| 		if(OperatingSystem.getOS().equalsIgnoreCase("osx")){ | 		if (OperatingSystem.getOS().equalsIgnoreCase("osx")) { | ||||||
| 			return " -XstartOnFirstThread"; | 			return " -XstartOnFirstThread"; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return ""; | 		return ""; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,25 +24,27 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; |  | ||||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; |  | ||||||
| import org.apache.commons.io.FileUtils; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| 
 | 
 | ||||||
| public class SetupIntelijRunConfigs { | import org.apache.commons.io.FileUtils; | ||||||
|  | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||||
|  | import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||||
|  | 
 | ||||||
|  | public class SetupIntelijRunConfigs { | ||||||
| 	public static void setup(Project project) { | 	public static void setup(Project project) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
| 		File projectDir = project.file(".idea"); | 		File projectDir = project.file(".idea"); | ||||||
| 		if(!projectDir.exists()){ | 
 | ||||||
|  | 		if (!projectDir.exists()) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		try { | 		try { | ||||||
| 			generate(project); | 			generate(project); | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
|  | @ -50,6 +52,7 @@ public class SetupIntelijRunConfigs { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		File runDir = new File(project.getRootDir(), extension.runDir); | 		File runDir = new File(project.getRootDir(), extension.runDir); | ||||||
|  | 
 | ||||||
| 		if (!runDir.exists()) { | 		if (!runDir.exists()) { | ||||||
| 			runDir.mkdirs(); | 			runDir.mkdirs(); | ||||||
| 		} | 		} | ||||||
|  | @ -57,7 +60,7 @@ public class SetupIntelijRunConfigs { | ||||||
| 
 | 
 | ||||||
| 	private static void generate(Project project) throws IOException { | 	private static void generate(Project project) throws IOException { | ||||||
| 		//Ensures the assets are downloaded when idea is syncing a project | 		//Ensures the assets are downloaded when idea is syncing a project | ||||||
| 		if(Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))){ | 		if (Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))) { | ||||||
| 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 			MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); | 			MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); | ||||||
| 			MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); | 			MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); | ||||||
|  | @ -68,18 +71,19 @@ public class SetupIntelijRunConfigs { | ||||||
| 		File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client.xml"); | 		File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client.xml"); | ||||||
| 		File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml"); | 		File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml"); | ||||||
| 
 | 
 | ||||||
| 		if(!runConfigsDir.exists()){ | 		if (!runConfigsDir.exists()) { | ||||||
| 			runConfigsDir.mkdirs(); | 			runConfigsDir.mkdirs(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); | 		String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); | ||||||
| 		String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); | 		String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); | ||||||
| 
 | 
 | ||||||
| 		if(!clientRunConfigs.exists()) | 		if (!clientRunConfigs.exists()) { | ||||||
| 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | ||||||
| 		if(!serverRunConfigs.exists()) | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!serverRunConfigs.exists()) { | ||||||
| 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | ||||||
| 
 | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,31 +24,26 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import com.google.common.collect.ImmutableMap; | import java.io.File; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import java.io.IOException; | ||||||
| import net.fabricmc.loom.providers.MappingsProvider; | import java.nio.file.Files; | ||||||
| import net.fabricmc.mappings.*; | import java.nio.file.Path; | ||||||
| import net.fabricmc.stitch.util.Pair; | 
 | ||||||
| import net.fabricmc.stitch.util.StitchUtil; |  | ||||||
| import org.cadixdev.lorenz.MappingSet; | import org.cadixdev.lorenz.MappingSet; | ||||||
| import org.cadixdev.lorenz.io.MappingsReader; | import org.cadixdev.lorenz.io.MappingsReader; | ||||||
| import org.cadixdev.lorenz.io.TextMappingsReader; |  | ||||||
| import org.cadixdev.lorenz.model.Mapping; |  | ||||||
| import org.cadixdev.mercury.Mercury; | import org.cadixdev.mercury.Mercury; | ||||||
| import org.cadixdev.mercury.remapper.MercuryRemapper; | import org.cadixdev.mercury.remapper.MercuryRemapper; | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.gradle.internal.impldep.aQute.bnd.build.Run; |  | ||||||
| import org.objectweb.asm.commons.Remapper; |  | ||||||
| import org.zeroturnaround.zip.ZipUtil; | import org.zeroturnaround.zip.ZipUtil; | ||||||
|  | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import java.io.*; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import java.net.URI; | import net.fabricmc.loom.providers.MappingsProvider; | ||||||
| import java.nio.file.*; | import net.fabricmc.mappings.ClassEntry; | ||||||
| import java.nio.file.attribute.BasicFileAttributes; | import net.fabricmc.mappings.EntryTriple; | ||||||
| import java.util.ArrayList; | import net.fabricmc.mappings.FieldEntry; | ||||||
| import java.util.HashMap; | import net.fabricmc.mappings.Mappings; | ||||||
| import java.util.List; | import net.fabricmc.mappings.MethodEntry; | ||||||
| import java.util.Map; | import net.fabricmc.stitch.util.StitchUtil; | ||||||
| 
 | 
 | ||||||
| public class SourceRemapper { | public class SourceRemapper { | ||||||
| 	public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception { | 	public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception { | ||||||
|  | @ -79,11 +74,13 @@ public class SourceRemapper { | ||||||
| 			for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | 			for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | ||||||
| 				m.getClassPath().add(file.toPath()); | 				m.getClassPath().add(file.toPath()); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			if (!toNamed) { | 			if (!toNamed) { | ||||||
| 				for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | 				for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | ||||||
| 					m.getClassPath().add(file.toPath()); | 					m.getClassPath().add(file.toPath()); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			for (Path file : extension.getUnmappedMods()) { | 			for (Path file : extension.getUnmappedMods()) { | ||||||
| 				if (Files.isRegularFile(file)) { | 				if (Files.isRegularFile(file)) { | ||||||
| 					m.getClassPath().add(file); | 					m.getClassPath().add(file); | ||||||
|  | @ -104,6 +101,7 @@ public class SourceRemapper { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar"); | 			source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar"); | ||||||
|  | 
 | ||||||
| 			try { | 			try { | ||||||
| 				com.google.common.io.Files.move(destination, source); | 				com.google.common.io.Files.move(destination, source); | ||||||
| 			} catch (IOException e) { | 			} catch (IOException e) { | ||||||
|  | @ -113,6 +111,7 @@ public class SourceRemapper { | ||||||
| 
 | 
 | ||||||
| 		Path srcPath = source.toPath(); | 		Path srcPath = source.toPath(); | ||||||
| 		boolean isSrcTmp = false; | 		boolean isSrcTmp = false; | ||||||
|  | 
 | ||||||
| 		if (!source.isDirectory()) { | 		if (!source.isDirectory()) { | ||||||
| 			// create tmp directory | 			// create tmp directory | ||||||
| 			isSrcTmp = true; | 			isSrcTmp = true; | ||||||
|  | @ -144,27 +143,27 @@ public class SourceRemapper { | ||||||
| 		if (isSrcTmp) { | 		if (isSrcTmp) { | ||||||
| 			Files.walkFileTree(srcPath, new DeletingFileVisitor()); | 			Files.walkFileTree(srcPath, new DeletingFileVisitor()); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|     private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { | 	private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { | ||||||
|         Files.walk(from).forEach(path -> { | 		Files.walk(from).forEach(path -> { | ||||||
|             Path targetPath = to.resolve(from.relativize(path).toString()); | 			Path targetPath = to.resolve(from.relativize(path).toString()); | ||||||
|             if (!isJavaFile(path) && !Files.exists(targetPath)) { |  | ||||||
|                 try { |  | ||||||
|                     Files.copy(path, targetPath); |  | ||||||
|                 } catch (IOException e) { |  | ||||||
|                     project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private static boolean isJavaFile(Path path) { | 			if (!isJavaFile(path) && !Files.exists(targetPath)) { | ||||||
|         String name = path.getFileName().toString(); | 				try { | ||||||
|         // ".java" is not a valid java file | 					Files.copy(path, targetPath); | ||||||
|         return name.endsWith(".java") && name.length() != 5; | 				} catch (IOException e) { | ||||||
|     } | 					project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static boolean isJavaFile(Path path) { | ||||||
|  | 		String name = path.getFileName().toString(); | ||||||
|  | 		// ".java" is not a valid java file | ||||||
|  | 		return name.endsWith(".java") && name.length() != 5; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	public static class TinyReader extends MappingsReader { | 	public static class TinyReader extends MappingsReader { | ||||||
| 		private final Mappings m; | 		private final Mappings m; | ||||||
|  | @ -179,35 +178,27 @@ public class SourceRemapper { | ||||||
| 		@Override | 		@Override | ||||||
| 		public MappingSet read(final MappingSet mappings) { | 		public MappingSet read(final MappingSet mappings) { | ||||||
| 			for (ClassEntry entry : m.getClassEntries()) { | 			for (ClassEntry entry : m.getClassEntries()) { | ||||||
| 				mappings.getOrCreateClassMapping(entry.get(from)) | 				mappings.getOrCreateClassMapping(entry.get(from)).setDeobfuscatedName(entry.get(to)); | ||||||
| 						.setDeobfuscatedName(entry.get(to)); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			for (FieldEntry entry : m.getFieldEntries()) { | 			for (FieldEntry entry : m.getFieldEntries()) { | ||||||
| 				EntryTriple fromEntry = entry.get(from); | 				EntryTriple fromEntry = entry.get(from); | ||||||
| 				EntryTriple toEntry = entry.get(to); | 				EntryTriple toEntry = entry.get(to); | ||||||
| 
 | 
 | ||||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()) | 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||||
| 						.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()) |  | ||||||
| 						.setDeobfuscatedName(toEntry.getName()); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			for (MethodEntry entry : m.getMethodEntries()) { | 			for (MethodEntry entry : m.getMethodEntries()) { | ||||||
| 				EntryTriple fromEntry = entry.get(from); | 				EntryTriple fromEntry = entry.get(from); | ||||||
| 				EntryTriple toEntry = entry.get(to); | 				EntryTriple toEntry = entry.get(to); | ||||||
| 
 | 
 | ||||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()) | 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||||
| 						.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()) |  | ||||||
| 						.setDeobfuscatedName(toEntry.getName()); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return mappings; | 			return mappings; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		@Override | 		@Override | ||||||
| 		public void close() throws IOException { | 		public void close() throws IOException { } | ||||||
| 
 |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,63 +24,66 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.mappings.Mappings; |  | ||||||
| import org.gradle.api.logging.Logging; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.nio.file.FileSystems; | ||||||
| import java.lang.ref.SoftReference; | import java.nio.file.Files; | ||||||
| import java.nio.file.*; | import java.nio.file.Path; | ||||||
|  | import java.nio.file.StandardWatchEventKinds; | ||||||
|  | import java.nio.file.WatchEvent; | ||||||
|  | import java.nio.file.WatchKey; | ||||||
|  | import java.nio.file.WatchService; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
| public final class StaticPathWatcher { | public final class StaticPathWatcher { | ||||||
|     public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); | 	public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); | ||||||
| 
 | 
 | ||||||
|     private final Map<Path, Boolean> changeCache = new HashMap<>(); | 	private final Map<Path, Boolean> changeCache = new HashMap<>(); | ||||||
|     private final WatchService service; | 	private final WatchService service; | ||||||
|     private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); | 	private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); | ||||||
| 
 | 
 | ||||||
|     private StaticPathWatcher() { | 	private StaticPathWatcher() { | ||||||
|         try { | 		try { | ||||||
|             service = FileSystems.getDefault().newWatchService(); | 			service = FileSystems.getDefault().newWatchService(); | ||||||
|         } catch (IOException e) { | 		} catch (IOException e) { | ||||||
|             throw new RuntimeException(e); | 			throw new RuntimeException(e); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     public boolean hasFileChanged(Path filePath) { | 	public boolean hasFileChanged(Path filePath) { | ||||||
|     	if(!Files.exists(filePath)){ | 		if (!Files.exists(filePath)) { | ||||||
|     		return true; | 			return true; | ||||||
| 	    } | 		} | ||||||
|         WatchKey key; |  | ||||||
|         while ((key = service.poll()) != null) { |  | ||||||
|             for (WatchEvent<?> event : key.pollEvents()) { |  | ||||||
|                 Object ctx = event.context(); |  | ||||||
|                 if (ctx instanceof Path) { |  | ||||||
|                     changeCache.put(((Path) ctx).toAbsolutePath(), true); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         filePath = filePath.toAbsolutePath(); | 		WatchKey key; | ||||||
|         Path parentPath = filePath.getParent(); |  | ||||||
|         if (changeCache.containsKey(filePath)) { |  | ||||||
|             return true; |  | ||||||
|         } else { |  | ||||||
|             if (!pathsObserved.containsKey(parentPath)) { |  | ||||||
|                 try { |  | ||||||
|                     pathsObserved.put(parentPath, parentPath.register( |  | ||||||
|                             service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE |  | ||||||
|                     )); |  | ||||||
| 
 | 
 | ||||||
|                     return true; | 		while ((key = service.poll()) != null) { | ||||||
|                 } catch (IOException e) { | 			for (WatchEvent<?> event : key.pollEvents()) { | ||||||
|                     throw new RuntimeException(e); | 				Object ctx = event.context(); | ||||||
|                 } | 
 | ||||||
|             } else { | 				if (ctx instanceof Path) { | ||||||
|                 return false; | 					changeCache.put(((Path) ctx).toAbsolutePath(), true); | ||||||
|             } | 				} | ||||||
|         } | 			} | ||||||
|     } | 		} | ||||||
|  | 
 | ||||||
|  | 		filePath = filePath.toAbsolutePath(); | ||||||
|  | 		Path parentPath = filePath.getParent(); | ||||||
|  | 
 | ||||||
|  | 		if (changeCache.containsKey(filePath)) { | ||||||
|  | 			return true; | ||||||
|  | 		} else { | ||||||
|  | 			if (!pathsObserved.containsKey(parentPath)) { | ||||||
|  | 				try { | ||||||
|  | 					pathsObserved.put(parentPath, parentPath.register(service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE)); | ||||||
|  | 
 | ||||||
|  | 					return true; | ||||||
|  | 				} catch (IOException e) { | ||||||
|  | 					throw new RuntimeException(e); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,14 +24,16 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.mappings.*; | import net.fabricmc.mappings.ClassEntry; | ||||||
|  | import net.fabricmc.mappings.EntryTriple; | ||||||
|  | import net.fabricmc.mappings.FieldEntry; | ||||||
|  | import net.fabricmc.mappings.Mappings; | ||||||
|  | import net.fabricmc.mappings.MethodEntry; | ||||||
| import net.fabricmc.tinyremapper.IMappingProvider; | import net.fabricmc.tinyremapper.IMappingProvider; | ||||||
| import net.fabricmc.tinyremapper.MemberInstance; | import net.fabricmc.tinyremapper.MemberInstance; | ||||||
| 
 | 
 | ||||||
| public class TinyRemapperMappingsHelper { | public class TinyRemapperMappingsHelper { | ||||||
| 	private TinyRemapperMappingsHelper() { | 	private TinyRemapperMappingsHelper() { } | ||||||
| 
 |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	public static IMappingProvider create(Mappings mappings, String from, String to) { | 	public static IMappingProvider create(Mappings mappings, String from, String to) { | ||||||
| 		return (classMap, fieldMap, methodMap) -> { | 		return (classMap, fieldMap, methodMap) -> { | ||||||
|  |  | ||||||
|  | @ -25,7 +25,6 @@ | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
| public class Version { | public class Version { | ||||||
| 
 |  | ||||||
| 	private String mappingsVersion; | 	private String mappingsVersion; | ||||||
| 	private String minecraftVersion; | 	private String minecraftVersion; | ||||||
| 
 | 
 | ||||||
|  | @ -34,7 +33,7 @@ public class Version { | ||||||
| 	public Version(String version) { | 	public Version(String version) { | ||||||
| 		this.version = version; | 		this.version = version; | ||||||
| 
 | 
 | ||||||
| 		if(version.contains("+build.")){ | 		if (version.contains("+build.")) { | ||||||
| 			this.minecraftVersion = version.substring(0, version.lastIndexOf('+')); | 			this.minecraftVersion = version.substring(0, version.lastIndexOf('+')); | ||||||
| 			this.mappingsVersion = version.substring(version.lastIndexOf('.') + 1); | 			this.mappingsVersion = version.substring(version.lastIndexOf('.') + 1); | ||||||
| 		} else { | 		} else { | ||||||
|  | @ -57,4 +56,4 @@ public class Version { | ||||||
| 	public String toString() { | 	public String toString() { | ||||||
| 		return version; | 		return version; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -54,4 +54,4 @@ public class AssetObject { | ||||||
| 		result = 31 * result + (int) (this.size ^ this.size >>> 32); | 		result = 31 * result + (int) (this.size ^ this.size >>> 32); | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,13 +24,13 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util.progress; | package net.fabricmc.loom.util.progress; | ||||||
| 
 | 
 | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
| 
 | 
 | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Wrapper to ProgressLogger internal API |  * Wrapper to ProgressLogger internal API. | ||||||
|  */ |  */ | ||||||
| public class ProgressLogger { | public class ProgressLogger { | ||||||
| 	private final Object logger; | 	private final Object logger; | ||||||
|  | @ -54,6 +54,7 @@ public class ProgressLogger { | ||||||
| 
 | 
 | ||||||
| 	private static Class<?> getFactoryClass() { | 	private static Class<?> getFactoryClass() { | ||||||
| 		Class<?> progressLoggerFactoryClass = null; | 		Class<?> progressLoggerFactoryClass = null; | ||||||
|  | 
 | ||||||
| 		try { | 		try { | ||||||
| 			//Gradle 2.14 and higher | 			//Gradle 2.14 and higher | ||||||
| 			progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory"); | 			progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory"); | ||||||
|  | @ -65,6 +66,7 @@ public class ProgressLogger { | ||||||
| 				// Unsupported Gradle version | 				// Unsupported Gradle version | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return progressLoggerFactoryClass; | 		return progressLoggerFactoryClass; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -73,9 +75,10 @@ public class ProgressLogger { | ||||||
| 			try { | 			try { | ||||||
| 				return logger.getClass().getMethod(methodName, args); | 				return logger.getClass().getMethod(methodName, args); | ||||||
| 			} catch (NoSuchMethodException ignored) { | 			} catch (NoSuchMethodException ignored) { | ||||||
| 
 | 				//Nope | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -85,14 +88,15 @@ public class ProgressLogger { | ||||||
| 				method.setAccessible(true); | 				method.setAccessible(true); | ||||||
| 				return method.invoke(logger, args); | 				return method.invoke(logger, args); | ||||||
| 			} catch (IllegalAccessException | InvocationTargetException ignored) { | 			} catch (IllegalAccessException | InvocationTargetException ignored) { | ||||||
| 
 | 				//Nope | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get a Progress logger from the Gradle internal API | 	 * Get a Progress logger from the Gradle internal API. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param project The project | 	 * @param project The project | ||||||
| 	 * @param category The logger category | 	 * @param category The logger category | ||||||
|  | @ -122,9 +126,9 @@ public class ProgressLogger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * <p>Sets the description of the operation. This should be a full, stand-alone description of the operation. | 	 * Sets the description of the operation. This should be a full, stand-alone description of the operation. | ||||||
| 	 * <p> | 	 * | ||||||
| 	 * <p>This must be called before {@link #started()}. | 	 * <p>This must be called before {@link #started()} | ||||||
| 	 * | 	 * | ||||||
| 	 * @param description The description. | 	 * @param description The description. | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -143,8 +147,8 @@ public class ProgressLogger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * <p>Sets the short description of the operation. This is used in place of the full description when display space is limited. | 	 * Sets the short description of the operation. This is used in place of the full description when display space is limited. | ||||||
| 	 * <p> | 	 * | ||||||
| 	 * <p>This must be called before {@link #started()} | 	 * <p>This must be called before {@link #started()} | ||||||
| 	 * | 	 * | ||||||
| 	 * @param description The short description. | 	 * @param description The short description. | ||||||
|  | @ -155,9 +159,9 @@ public class ProgressLogger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * <p>Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | 	 * Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||||
| 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | ||||||
| 	 * <p> | 	 * | ||||||
| 	 * <p>If not specified, no logging header is logged. | 	 * <p>If not specified, no logging header is logged. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return The logging header, possibly empty. | 	 * @return The logging header, possibly empty. | ||||||
|  | @ -167,7 +171,7 @@ public class ProgressLogger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * <p>Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | 	 * Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||||
| 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param header The header. May be empty or null. | 	 * @param header The header. May be empty or null. | ||||||
|  | @ -213,7 +217,7 @@ public class ProgressLogger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Logs the completion of the operation, with no final status | 	 * Logs the completion of the operation, with no final status. | ||||||
| 	 */ | 	 */ | ||||||
| 	public void completed() { | 	public void completed() { | ||||||
| 		invoke(completed); | 		invoke(completed); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue