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
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -18,3 +18,5 @@ | |||
| !/README.md | ||||
| !/settings.gradle | ||||
| !/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 'eclipse' | ||||
| 	id 'groovy' | ||||
| 	id 'checkstyle' | ||||
| } | ||||
| 
 | ||||
| sourceCompatibility = 1.8 | ||||
|  | @ -60,6 +61,12 @@ dependencies { | |||
| 	testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") | ||||
| } | ||||
| 
 | ||||
| configurations.all { | ||||
| 	resolutionStrategy { | ||||
| 		force 'org.codehaus.groovy:groovy-all:2.4.12' | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| jar { | ||||
| 	manifest { | ||||
| 		attributes 'Implementation-Version': version + " Build(" + build + ")" | ||||
|  | @ -82,6 +89,15 @@ license { | |||
| 	exclude '**/loom/util/DownloadUtil.java' | ||||
| } | ||||
| 
 | ||||
| checkstyle { | ||||
| 	configFile = file("checkstyle.xml") | ||||
| 	toolVersion = '8.25' | ||||
| } | ||||
| 
 | ||||
| checkstyleMain { | ||||
| 	logging.setLevel(LogLevel.LIFECYCLE) | ||||
| } | ||||
| 
 | ||||
| gradlePlugin { | ||||
| 	plugins { | ||||
| 		fabricLoom { | ||||
|  |  | |||
							
								
								
									
										162
									
								
								checkstyle.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| import java.util.Optional; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| import groovy.util.Node; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.task.RemapJarTask; | ||||
| import net.fabricmc.loom.task.RemapSourcesJarTask; | ||||
| import net.fabricmc.loom.util.*; | ||||
| import org.gradle.api.Plugin; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
|  | @ -54,13 +57,16 @@ import org.gradle.api.tasks.scala.ScalaCompile; | |||
| import org.gradle.plugins.ide.eclipse.model.EclipseModel; | ||||
| import org.gradle.plugins.ide.idea.model.IdeaModel; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| import java.util.Optional; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.task.RemapJarTask; | ||||
| import net.fabricmc.loom.task.RemapSourcesJarTask; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.GroovyXmlUtil; | ||||
| import net.fabricmc.loom.util.LoomDependencyManager; | ||||
| import net.fabricmc.loom.util.NestedJars; | ||||
| import net.fabricmc.loom.util.RemappedConfigurationEntry; | ||||
| import net.fabricmc.loom.util.SetupIntelijRunConfigs; | ||||
| 
 | ||||
| public class AbstractPlugin implements Plugin<Project> { | ||||
| 	protected Project project; | ||||
|  | @ -116,6 +122,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 			compileModsMappedConfig.setTransitive(false); // Don't get transitive deps of already remapped mods | ||||
| 
 | ||||
| 			extendsFrom(entry.getTargetConfiguration(project.getConfigurations()), entry.getRemappedConfiguration()); | ||||
| 
 | ||||
| 			if (entry.isOnModCompileClasspath()) { | ||||
| 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH, entry.getSourceConfiguration()); | ||||
| 				extendsFrom(Constants.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration()); | ||||
|  | @ -137,15 +144,17 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 		configureScala(); | ||||
| 
 | ||||
| 		Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | ||||
| 
 | ||||
| 		for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | ||||
| 			Project project = entry.getKey(); | ||||
| 			Set<Task> taskSet = entry.getValue(); | ||||
| 
 | ||||
| 			for (Task task : taskSet) { | ||||
| 				if (task instanceof JavaCompile | ||||
| 						&& !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { | ||||
| 				if (task instanceof JavaCompile && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { | ||||
| 					JavaCompile javaCompileTask = (JavaCompile) task; | ||||
| 					javaCompileTask.doFirst(task1 -> { | ||||
| 						project.getLogger().lifecycle(":setting java compiler args"); | ||||
| 
 | ||||
| 						try { | ||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | ||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | ||||
|  | @ -166,30 +175,31 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 		return project; | ||||
| 	} | ||||
| 
 | ||||
|     protected void configureScala() { | ||||
|         project.afterEvaluate(proj -> { | ||||
|             if (project.getPluginManager().hasPlugin("scala")) { | ||||
|                 ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); | ||||
|                 LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|                 project.getLogger().warn(":configuring scala compilation processing"); | ||||
|                 try { | ||||
|                     task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | ||||
|                     task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | ||||
|                     task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); | ||||
|                     task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); | ||||
|                 } catch (IOException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 	protected void configureScala() { | ||||
| 		project.afterEvaluate(proj -> { | ||||
| 			if (project.getPluginManager().hasPlugin("scala")) { | ||||
| 				ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); | ||||
| 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 				project.getLogger().warn(":configuring scala compilation processing"); | ||||
| 
 | ||||
| 				try { | ||||
| 					task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath()); | ||||
| 					task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath()); | ||||
| 					task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); | ||||
| 					task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); | ||||
| 				} catch (IOException e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Permit to add a Maven repository to a target project | ||||
| 	 * Permit to add a Maven repository to a target project. | ||||
| 	 * | ||||
| 	 * @param target The garget project | ||||
| 	 * @param name   The name of the repository | ||||
| 	 * @param url    The URL of the repository | ||||
| 	 * @param name The name of the repository | ||||
| 	 * @param url The URL of the repository | ||||
| 	 * @return An object containing the name and the URL of the repository that can be modified later | ||||
| 	 */ | ||||
| 	public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) { | ||||
|  | @ -200,7 +210,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Add Minecraft dependencies to IDE dependencies | ||||
| 	 * Add Minecraft dependencies to IDE dependencies. | ||||
| 	 */ | ||||
| 	protected void configureIDEs() { | ||||
| 		// IDEA | ||||
|  | @ -236,6 +246,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 		if (dep instanceof ResolvedDependencyResult) { | ||||
| 			if (dep.getFrom().getId() instanceof ModuleComponentIdentifier) { | ||||
| 				ModuleComponentIdentifier mci = ((ModuleComponentIdentifier) dep.getFrom().getId()); | ||||
| 
 | ||||
| 				if (predicate.test(mci)) { | ||||
| 					addModule(project, configuration, dep); | ||||
| 					found = true; | ||||
|  | @ -251,7 +262,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Add Minecraft dependencies to compile time | ||||
| 	 * Add Minecraft dependencies to compile time. | ||||
| 	 */ | ||||
| 	protected void configureCompile() { | ||||
| 		JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); | ||||
|  | @ -264,12 +275,18 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 
 | ||||
| 		// Add Mixin dependencies | ||||
| 		Project p = project; | ||||
| 
 | ||||
| 		while (true) { | ||||
| 			boolean found = false; | ||||
| 
 | ||||
| 			for (DependencyResult dep : p.getBuildscript().getConfigurations().getByName("classpath").getIncoming().getResolutionResult().getRoot().getDependencies()) { | ||||
| 				found = findAndAddModule(project, "annotationProcessor", dep, (mci) -> ("net.fabricmc".equals(mci.getGroup()) && "fabric-mixin-compile-extensions".equals(mci.getModule()))); | ||||
| 			} | ||||
| 			if (found || AbstractPlugin.isRootProject(p)) break; | ||||
| 
 | ||||
| 			if (found || AbstractPlugin.isRootProject(p)) { | ||||
| 				break; | ||||
| 			} | ||||
| 
 | ||||
| 			p = p.getRootProject(); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -330,6 +347,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 				RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar"); | ||||
| 
 | ||||
| 				assert remapJarTask != null; | ||||
| 
 | ||||
| 				if (!remapJarTask.getInput().isPresent()) { | ||||
| 					jarTask.setClassifier("dev"); | ||||
| 					remapJarTask.setClassifier(""); | ||||
|  | @ -344,8 +362,10 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 				project1.getTasks().getByName("build").dependsOn(remapJarTask); | ||||
| 
 | ||||
| 				Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | ||||
| 
 | ||||
| 				for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | ||||
| 					Set<Task> taskSet = entry.getValue(); | ||||
| 
 | ||||
| 					for (Task task : taskSet) { | ||||
| 						if (task instanceof RemapJarTask && ((RemapJarTask) task).getAddNestedDependencies().getOrElse(false)) { | ||||
| 							//Run all the sub project remap jars tasks before the root projects jar, this is to allow us to include projects | ||||
|  | @ -384,6 +404,7 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 
 | ||||
| 				// add modsCompile to maven-publish | ||||
| 				PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class); | ||||
| 
 | ||||
| 				if (mavenPublish != null) { | ||||
| 					mavenPublish.publications((publications) -> { | ||||
| 						for (Publication publication : publications) { | ||||
|  | @ -393,15 +414,14 @@ public class AbstractPlugin implements Plugin<Project> { | |||
| 										Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies"); | ||||
| 										Set<String> foundArtifacts = new HashSet<>(); | ||||
| 
 | ||||
| 										GroovyXmlUtil.childrenNodesStream(dependencies) | ||||
| 												.filter((n) -> "dependency".equals(n.name())) | ||||
| 												.forEach((n) -> { | ||||
| 													Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId"); | ||||
| 													Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId"); | ||||
| 													if (groupId.isPresent() && artifactId.isPresent()) { | ||||
| 														foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text()); | ||||
| 													} | ||||
| 												}); | ||||
| 										GroovyXmlUtil.childrenNodesStream(dependencies).filter((n) -> "dependency".equals(n.name())).forEach((n) -> { | ||||
| 											Optional<Node> groupId = GroovyXmlUtil.getNode(n, "groupId"); | ||||
| 											Optional<Node> artifactId = GroovyXmlUtil.getNode(n, "artifactId"); | ||||
| 
 | ||||
| 											if (groupId.isPresent() && artifactId.isPresent()) { | ||||
| 												foundArtifacts.add(groupId.get().text() + ":" + artifactId.get().text()); | ||||
| 											} | ||||
| 										}); | ||||
| 
 | ||||
| 										for (Dependency dependency : compileModsConfig.getAllDependencies()) { | ||||
| 											if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) { | ||||
|  |  | |||
|  | @ -24,28 +24,30 @@ | |||
| 
 | ||||
| package net.fabricmc.loom; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.nio.file.Path; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.function.BiPredicate; | ||||
| import java.util.function.Function; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import javax.annotation.Nullable; | ||||
| 
 | ||||
| import com.google.gson.JsonObject; | ||||
| import org.cadixdev.lorenz.MappingSet; | ||||
| import org.cadixdev.mercury.Mercury; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| 
 | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.util.LoomDependencyManager; | ||||
| import org.cadixdev.lorenz.MappingSet; | ||||
| import org.cadixdev.mercury.Mercury; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.UnknownDomainObjectException; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.component.ComponentIdentifier; | ||||
| import org.gradle.api.artifacts.component.ModuleComponentIdentifier; | ||||
| import org.gradle.api.artifacts.result.ResolvedArtifactResult; | ||||
| 
 | ||||
| import javax.annotation.Nullable; | ||||
| import java.io.File; | ||||
| import java.nio.file.Path; | ||||
| import java.util.*; | ||||
| import java.util.function.BiPredicate; | ||||
| import java.util.function.Function; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| public class LoomGradleExtension { | ||||
| 	public String runDir = "run"; | ||||
|  | @ -87,77 +89,93 @@ public class LoomGradleExtension { | |||
| 	} | ||||
| 
 | ||||
| 	public void setInstallerJson(JsonObject object, int priority) { | ||||
| 	    if (installerJson == null || priority <= installerJsonPriority) { | ||||
|             this.installerJson = object; | ||||
|             this.installerJsonPriority = priority; | ||||
|         } | ||||
|     } | ||||
| 		if (installerJson == null || priority <= installerJsonPriority) { | ||||
| 			this.installerJson = object; | ||||
| 			this.installerJsonPriority = priority; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     public JsonObject getInstallerJson() { | ||||
| 	    return installerJson; | ||||
|     } | ||||
| 	public JsonObject getInstallerJson() { | ||||
| 		return installerJson; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getUserCache() { | ||||
| 		File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom"); | ||||
| 
 | ||||
| 		if (!userCache.exists()) { | ||||
| 			userCache.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return userCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getRootProjectPersistentCache() { | ||||
| 		File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache"); | ||||
| 		if(!projectCache.exists()){ | ||||
| 
 | ||||
| 		if (!projectCache.exists()) { | ||||
| 			projectCache.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return projectCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getRootProjectBuildCache() { | ||||
| 		File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache"); | ||||
| 		if(!projectCache.exists()){ | ||||
| 
 | ||||
| 		if (!projectCache.exists()) { | ||||
| 			projectCache.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return projectCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getProjectBuildCache() { | ||||
| 		File projectCache = new File(project.getBuildDir(), "loom-cache"); | ||||
| 		if(!projectCache.exists()){ | ||||
| 
 | ||||
| 		if (!projectCache.exists()) { | ||||
| 			projectCache.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return projectCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getRemappedModCache() { | ||||
| 		File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods"); | ||||
| 
 | ||||
| 		if (!remappedModCache.exists()) { | ||||
| 			remappedModCache.mkdir(); | ||||
| 		} | ||||
| 
 | ||||
| 		return remappedModCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getNestedModCache() { | ||||
| 		File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods"); | ||||
| 
 | ||||
| 		if (!nestedModCache.exists()) { | ||||
| 			nestedModCache.mkdir(); | ||||
| 		} | ||||
| 
 | ||||
| 		return nestedModCache; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getNativesJarStore(){ | ||||
| 	public File getNativesJarStore() { | ||||
| 		File natives = new File(getUserCache(), "natives/jars"); | ||||
| 		if(!natives.exists()) { | ||||
| 
 | ||||
| 		if (!natives.exists()) { | ||||
| 			natives.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return natives; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getNativesDirectory(){ | ||||
| 	public File getNativesDirectory() { | ||||
| 		File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion); | ||||
| 		if(!natives.exists()) { | ||||
| 
 | ||||
| 		if (!natives.exists()) { | ||||
| 			natives.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		return natives; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -167,6 +185,7 @@ public class LoomGradleExtension { | |||
| 			for (Dependency dependency : config.getDependencies()) { | ||||
| 				String group = dependency.getGroup(); | ||||
| 				String name = dependency.getName(); | ||||
| 
 | ||||
| 				if (groupNameFilter.test(group, name)) { | ||||
| 					p.getLogger().debug("Loom findDependency found: " + group + ":" + name + ":" + dependency.getVersion()); | ||||
| 					return dependency; | ||||
|  | @ -181,12 +200,15 @@ public class LoomGradleExtension { | |||
| 	private <T> T recurseProjects(Function<Project, T> projectTFunction) { | ||||
| 		Project p = this.project; | ||||
| 		T result; | ||||
| 
 | ||||
| 		while (!AbstractPlugin.isRootProject(p)) { | ||||
| 			if ((result = projectTFunction.apply(p)) != null) { | ||||
| 				return result; | ||||
| 			} | ||||
| 
 | ||||
| 			p = p.getRootProject(); | ||||
| 		} | ||||
| 
 | ||||
| 		result = projectTFunction.apply(p); | ||||
| 		return result; | ||||
| 	} | ||||
|  | @ -197,9 +219,11 @@ public class LoomGradleExtension { | |||
| 			List<Configuration> configs = new ArrayList<>(); | ||||
| 			// check compile classpath first | ||||
| 			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); | ||||
| 
 | ||||
| 			if (possibleCompileClasspath != null) { | ||||
| 				configs.add(possibleCompileClasspath); | ||||
| 			} | ||||
| 
 | ||||
| 			// failing that, buildscript | ||||
| 			configs.addAll(p.getBuildscript().getConfigurations()); | ||||
| 
 | ||||
|  | @ -242,15 +266,15 @@ public class LoomGradleExtension { | |||
| 		return dependencyManager; | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftProvider getMinecraftProvider(){ | ||||
| 	public MinecraftProvider getMinecraftProvider() { | ||||
| 		return getDependencyManager().getProvider(MinecraftProvider.class); | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftMappedProvider getMinecraftMappedProvider(){ | ||||
| 	public MinecraftMappedProvider getMinecraftMappedProvider() { | ||||
| 		return getMappingsProvider().mappedProvider; | ||||
| 	} | ||||
| 
 | ||||
| 	public MappingsProvider getMappingsProvider(){ | ||||
| 	public MappingsProvider getMappingsProvider() { | ||||
| 		return getDependencyManager().getProvider(MappingsProvider.class); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -259,7 +283,7 @@ public class LoomGradleExtension { | |||
| 	} | ||||
| 
 | ||||
| 	public String getRefmapName() { | ||||
| 		if(refmapName == null || refmapName.isEmpty()){ | ||||
| 		if (refmapName == null || refmapName.isEmpty()) { | ||||
| 			project.getLogger().warn("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json"); | ||||
| 			refmapName = project.getName() + "-refmap.json"; | ||||
| 		} | ||||
|  |  | |||
|  | @ -24,26 +24,40 @@ | |||
| 
 | ||||
| package net.fabricmc.loom; | ||||
| 
 | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftLibraryProvider; | ||||
| import net.fabricmc.loom.task.*; | ||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.tasks.TaskContainer; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Locale; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.tasks.TaskContainer; | ||||
| 
 | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftLibraryProvider; | ||||
| import net.fabricmc.loom.task.AbstractDecompileTask; | ||||
| import net.fabricmc.loom.task.CleanLoomBinaries; | ||||
| import net.fabricmc.loom.task.CleanLoomMappings; | ||||
| import net.fabricmc.loom.task.DownloadAssetsTask; | ||||
| import net.fabricmc.loom.task.GenEclipseRunsTask; | ||||
| import net.fabricmc.loom.task.GenIdeaProjectTask; | ||||
| import net.fabricmc.loom.task.GenVsCodeProjectTask; | ||||
| import net.fabricmc.loom.task.MigrateMappingsTask; | ||||
| import net.fabricmc.loom.task.RemapJarTask; | ||||
| import net.fabricmc.loom.task.RemapLineNumbersTask; | ||||
| import net.fabricmc.loom.task.RemapSourcesJarTask; | ||||
| import net.fabricmc.loom.task.RunClientTask; | ||||
| import net.fabricmc.loom.task.RunServerTask; | ||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||
| 
 | ||||
| public class LoomGradlePlugin extends AbstractPlugin { | ||||
| 	private static File getMappedByproduct(Project project, String suffix) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||
| 		String path = mappedJar.getAbsolutePath(); | ||||
| 
 | ||||
| 		if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) { | ||||
| 			throw new RuntimeException("Invalid mapped JAR path: " + path); | ||||
| 		} | ||||
|  | @ -57,7 +71,6 @@ public class LoomGradlePlugin extends AbstractPlugin { | |||
| 
 | ||||
| 		TaskContainer tasks = target.getTasks(); | ||||
| 
 | ||||
| 
 | ||||
| 		tasks.register("cleanLoomBinaries", CleanLoomBinaries.class); | ||||
| 		tasks.register("cleanLoomMappings", CleanLoomMappings.class); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,41 +24,42 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.StaticPathWatcher; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.ref.SoftReference; | ||||
| import java.nio.file.*; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.StaticPathWatcher; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| 
 | ||||
| public final class MappingsCache { | ||||
|     public static final MappingsCache INSTANCE = new MappingsCache(); | ||||
| 	public static final MappingsCache INSTANCE = new MappingsCache(); | ||||
| 
 | ||||
|     private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); | ||||
| 	private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); | ||||
| 
 | ||||
|     public Mappings get(Path mappingsPath) { | ||||
|         mappingsPath = mappingsPath.toAbsolutePath(); | ||||
|         if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { | ||||
|             mappingsCache.remove(mappingsPath); | ||||
|         } | ||||
| 	public Mappings get(Path mappingsPath) { | ||||
| 		mappingsPath = mappingsPath.toAbsolutePath(); | ||||
| 
 | ||||
|         SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); | ||||
|         if (ref != null && ref.get() != null) { | ||||
|             return ref.get(); | ||||
|         } else { | ||||
|             try (InputStream stream = Files.newInputStream(mappingsPath)) { | ||||
|                 Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||
|                 ref = new SoftReference<>(mappings); | ||||
|                 mappingsCache.put(mappingsPath, ref); | ||||
|                 return mappings; | ||||
|             } catch (IOException e) { | ||||
|                 throw new RuntimeException(e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 		if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { | ||||
| 			mappingsCache.remove(mappingsPath); | ||||
| 		} | ||||
| 
 | ||||
| 		SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); | ||||
| 
 | ||||
| 		if (ref != null && ref.get() != null) { | ||||
| 			return ref.get(); | ||||
| 		} else { | ||||
| 			try (InputStream stream = Files.newInputStream(mappingsPath)) { | ||||
| 				Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||
| 				ref = new SoftReference<>(mappings); | ||||
| 				mappingsCache.put(mappingsPath, ref); | ||||
| 				return mappings; | ||||
| 			} catch (IOException e) { | ||||
| 				throw new RuntimeException(e); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,23 +24,22 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.FileSystem; | ||||
| import java.nio.file.FileSystems; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DependencyProvider; | ||||
| import net.fabricmc.loom.util.Version; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import net.fabricmc.stitch.commands.CommandProposeFieldNames; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.lang.ref.SoftReference; | ||||
| import java.nio.file.FileSystem; | ||||
| import java.nio.file.FileSystems; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| //TODO fix local mappings | ||||
| //TODO possibly use maven for mappings, can fix above at the same time | ||||
|  | @ -84,6 +83,7 @@ public class MappingsProvider extends DependencyProvider { | |||
| 		if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) { | ||||
| 			if (!MAPPINGS_TINY_BASE.exists()) { | ||||
| 				project.getLogger().lifecycle(":extracting " + mappingsJar.getName()); | ||||
| 
 | ||||
| 				try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) { | ||||
| 					Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny"); | ||||
| 					Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath()); | ||||
|  | @ -95,11 +95,7 @@ public class MappingsProvider extends DependencyProvider { | |||
| 			} | ||||
| 
 | ||||
| 			project.getLogger().lifecycle(":populating field names"); | ||||
| 			new CommandProposeFieldNames().run(new String[] { | ||||
| 					minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), | ||||
| 					MAPPINGS_TINY_BASE.getAbsolutePath(), | ||||
| 					MAPPINGS_TINY.getAbsolutePath() | ||||
| 			}); | ||||
| 			new CommandProposeFieldNames().run(new String[]{minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), MAPPINGS_TINY_BASE.getAbsolutePath(), MAPPINGS_TINY.getAbsolutePath()}); | ||||
| 		} | ||||
| 
 | ||||
| 		mappedProvider = new MinecraftMappedProvider(); | ||||
|  |  | |||
|  | @ -24,7 +24,16 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Checksum; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
|  | @ -34,15 +43,6 @@ import net.fabricmc.loom.util.assets.AssetIndex; | |||
| import net.fabricmc.loom.util.assets.AssetObject; | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| 
 | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public class MinecraftAssetsProvider { | ||||
| 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|  | @ -53,13 +53,16 @@ public class MinecraftAssetsProvider { | |||
| 
 | ||||
| 		// get existing cache files | ||||
| 		File assets = new File(extension.getUserCache(), "assets"); | ||||
| 
 | ||||
| 		if (!assets.exists()) { | ||||
| 			assets.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json"); | ||||
| 
 | ||||
| 		if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { | ||||
| 			project.getLogger().lifecycle(":downloading asset index"); | ||||
| 
 | ||||
| 			if (offline) { | ||||
| 				if (assetsInfo.exists()) { | ||||
| 					//We know it's outdated but can't do anything about it, oh well | ||||
|  | @ -76,13 +79,16 @@ public class MinecraftAssetsProvider { | |||
| 		ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); | ||||
| 		progressLogger.start("Downloading assets...", "assets"); | ||||
| 		AssetIndex index; | ||||
| 
 | ||||
| 		try (FileReader fileReader = new FileReader(assetsInfo)) { | ||||
| 			index = new Gson().fromJson(fileReader, AssetIndex.class); | ||||
| 		} | ||||
| 
 | ||||
| 		Map<String, AssetObject> parent = index.getFileMap(); | ||||
| 		final int totalSize = parent.size(); | ||||
| 		int position = 0; | ||||
| 		project.getLogger().lifecycle(":downloading assets..."); | ||||
| 
 | ||||
| 		for (Map.Entry<String, AssetObject> entry : parent.entrySet()) { | ||||
| 			AssetObject object = entry.getValue(); | ||||
| 			String sha1 = object.getHash(); | ||||
|  | @ -101,11 +107,14 @@ public class MinecraftAssetsProvider { | |||
| 					DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			String assetName = entry.getKey(); | ||||
| 			int end = assetName.lastIndexOf("/") + 1; | ||||
| 
 | ||||
| 			if (end > 0) { | ||||
| 				assetName = assetName.substring(end); | ||||
| 			} | ||||
| 
 | ||||
| 			progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded"); | ||||
| 			position++; | ||||
| 		} | ||||
|  |  | |||
|  | @ -24,27 +24,18 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Checksum; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| import net.fabricmc.loom.util.assets.AssetIndex; | ||||
| import net.fabricmc.loom.util.assets.AssetObject; | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.Collection; | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| 
 | ||||
| public class MinecraftLibraryProvider { | ||||
| 
 | ||||
| 	public File MINECRAFT_LIBS; | ||||
| 
 | ||||
| 	private Collection<File> libs = new HashSet<>(); | ||||
|  | @ -61,6 +52,7 @@ public class MinecraftLibraryProvider { | |||
| 
 | ||||
| 				// By default, they are all available on all sides | ||||
| 				/* boolean isClientOnly = false; | ||||
| 
 | ||||
| 				if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) { | ||||
| 					isClientOnly = true; | ||||
| 				} */ | ||||
|  | @ -78,5 +70,4 @@ public class MinecraftLibraryProvider { | |||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -24,73 +24,76 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DependencyProvider; | ||||
| import net.fabricmc.loom.util.MapJarsTiny; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.Collection; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DependencyProvider; | ||||
| import net.fabricmc.loom.util.MapJarsTiny; | ||||
| 
 | ||||
| public class MinecraftMappedProvider extends DependencyProvider { | ||||
|     public File MINECRAFT_MAPPED_JAR; | ||||
|     public File MINECRAFT_INTERMEDIARY_JAR; | ||||
| 	public File MINECRAFT_MAPPED_JAR; | ||||
| 	public File MINECRAFT_INTERMEDIARY_JAR; | ||||
| 
 | ||||
|     private MinecraftProvider minecraftProvider; | ||||
| 	private MinecraftProvider minecraftProvider; | ||||
| 
 | ||||
|     @Override | ||||
|     public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
|         if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { | ||||
|             throw new RuntimeException("mappings file not found"); | ||||
|         } | ||||
| 	@Override | ||||
| 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
| 		if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { | ||||
| 			throw new RuntimeException("mappings file not found"); | ||||
| 		} | ||||
| 
 | ||||
|         if (!extension.getMinecraftProvider().getMergedJar().exists()) { | ||||
|             throw new RuntimeException("input merged jar not found"); | ||||
|         } | ||||
| 		if (!extension.getMinecraftProvider().getMergedJar().exists()) { | ||||
| 			throw new RuntimeException("input merged jar not found"); | ||||
| 		} | ||||
| 
 | ||||
|         if(!getMappedJar().exists() || !getIntermediaryJar().exists()){ | ||||
|             if (getMappedJar().exists()) { | ||||
|                 getMappedJar().delete(); | ||||
|             } | ||||
|             if (getIntermediaryJar().exists()) { | ||||
|                 getIntermediaryJar().delete(); | ||||
|             } | ||||
|             new MapJarsTiny().mapJars(minecraftProvider, this, project); | ||||
|         } | ||||
| 		if (!getMappedJar().exists() || !getIntermediaryJar().exists()) { | ||||
| 			if (getMappedJar().exists()) { | ||||
| 				getMappedJar().delete(); | ||||
| 			} | ||||
| 
 | ||||
|         if (!MINECRAFT_MAPPED_JAR.exists()) { | ||||
|             throw new RuntimeException("mapped jar not found"); | ||||
|         } | ||||
| 			if (getIntermediaryJar().exists()) { | ||||
| 				getIntermediaryJar().delete(); | ||||
| 			} | ||||
| 
 | ||||
|         String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion; | ||||
|         project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||
|         version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName; | ||||
|         project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||
|     } | ||||
| 			new MapJarsTiny().mapJars(minecraftProvider, this, project); | ||||
| 		} | ||||
| 
 | ||||
|     public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | ||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|         this.minecraftProvider = minecraftProvider; | ||||
|         MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-"  + mappingsProvider.mappingsName + ".jar"); | ||||
|         MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar"); | ||||
|     } | ||||
| 		if (!MINECRAFT_MAPPED_JAR.exists()) { | ||||
| 			throw new RuntimeException("mapped jar not found"); | ||||
| 		} | ||||
| 
 | ||||
|     public Collection<File> getMapperPaths() { | ||||
|         return minecraftProvider.libraryProvider.getLibraries(); | ||||
|     } | ||||
| 		String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion; | ||||
| 		project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||
| 		version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName; | ||||
| 		project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version)); | ||||
| 	} | ||||
| 
 | ||||
|     public File getIntermediaryJar() { | ||||
|         return MINECRAFT_INTERMEDIARY_JAR; | ||||
|     } | ||||
| 	public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		this.minecraftProvider = minecraftProvider; | ||||
| 		MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-" + mappingsProvider.mappingsName + ".jar"); | ||||
| 		MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar"); | ||||
| 	} | ||||
| 
 | ||||
|     public File getMappedJar() { | ||||
|         return MINECRAFT_MAPPED_JAR; | ||||
|     } | ||||
| 	public Collection<File> getMapperPaths() { | ||||
| 		return minecraftProvider.libraryProvider.getLibraries(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public String getTargetConfig() { | ||||
|         return Constants.MINECRAFT_NAMED; | ||||
|     } | ||||
| 	public File getIntermediaryJar() { | ||||
| 		return MINECRAFT_INTERMEDIARY_JAR; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getMappedJar() { | ||||
| 		return MINECRAFT_MAPPED_JAR; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getTargetConfig() { | ||||
| 		return Constants.MINECRAFT_NAMED; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,18 +24,18 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| import org.gradle.api.Project; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| 
 | ||||
| public class MinecraftNativesProvider { | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| 
 | ||||
| public class MinecraftNativesProvider { | ||||
| 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MinecraftVersionInfo versionInfo = minecraftProvider.versionInfo; | ||||
|  | @ -45,6 +45,7 @@ public class MinecraftNativesProvider { | |||
| 
 | ||||
| 		for (MinecraftVersionInfo.Library library : versionInfo.libraries) { | ||||
| 			File libJarFile = library.getFile(jarStore); | ||||
| 
 | ||||
| 			if (library.allowed() && library.isNative() && libJarFile != null) { | ||||
| 				DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger()); | ||||
| 
 | ||||
|  | @ -53,5 +54,4 @@ public class MinecraftNativesProvider { | |||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -24,17 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import com.google.common.io.Files; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.*; | ||||
| import net.fabricmc.stitch.merge.JarMerger; | ||||
| 
 | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
|  | @ -44,8 +33,24 @@ import java.util.Optional; | |||
| import java.util.function.Consumer; | ||||
| import java.util.zip.ZipError; | ||||
| 
 | ||||
| public class MinecraftProvider extends DependencyProvider { | ||||
| import com.google.common.io.Files; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Checksum; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DependencyProvider; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.ManifestVersion; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| import net.fabricmc.loom.util.StaticPathWatcher; | ||||
| import net.fabricmc.stitch.merge.JarMerger; | ||||
| 
 | ||||
| public class MinecraftProvider extends DependencyProvider { | ||||
| 	public String minecraftVersion; | ||||
| 
 | ||||
| 	public MinecraftVersionInfo versionInfo; | ||||
|  | @ -66,25 +71,26 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 		initFiles(project); | ||||
| 
 | ||||
| 		downloadMcJson(project, offline); | ||||
| 
 | ||||
| 		try (FileReader reader = new FileReader(MINECRAFT_JSON)) { | ||||
| 			versionInfo = gson.fromJson(reader, MinecraftVersionInfo.class); | ||||
| 		} | ||||
| 
 | ||||
| 		// Add Loom as an annotation processor | ||||
|         addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly"); | ||||
| 		addDependency(project.files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), project, "compileOnly"); | ||||
| 
 | ||||
|         if (offline) { | ||||
|         	if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) { | ||||
|         		project.getLogger().debug("Found client and server jars, presuming up-to-date"); | ||||
|         	} else if (MINECRAFT_MERGED_JAR.exists()) { | ||||
|         		//Strictly we don't need the split jars if the merged one exists, let's try go on | ||||
|         		project.getLogger().warn("Missing game jar but merged jar present, things might end badly"); | ||||
|         	} else { | ||||
|         		throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists()); | ||||
|         	} | ||||
|         } else { | ||||
|         	downloadJars(project.getLogger()); | ||||
|         } | ||||
| 		if (offline) { | ||||
| 			if (MINECRAFT_CLIENT_JAR.exists() && MINECRAFT_SERVER_JAR.exists()) { | ||||
| 				project.getLogger().debug("Found client and server jars, presuming up-to-date"); | ||||
| 			} else if (MINECRAFT_MERGED_JAR.exists()) { | ||||
| 				//Strictly we don't need the split jars if the merged one exists, let's try go on | ||||
| 				project.getLogger().warn("Missing game jar but merged jar present, things might end badly"); | ||||
| 			} else { | ||||
| 				throw new GradleException("Missing jar(s); Client: " + MINECRAFT_CLIENT_JAR.exists() + ", Server: " + MINECRAFT_SERVER_JAR.exists()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			downloadJars(project.getLogger()); | ||||
| 		} | ||||
| 
 | ||||
| 		libraryProvider = new MinecraftLibraryProvider(); | ||||
| 		libraryProvider.provide(this, project); | ||||
|  | @ -108,7 +114,6 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 		MINECRAFT_CLIENT_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); | ||||
| 		MINECRAFT_SERVER_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); | ||||
| 		MINECRAFT_MERGED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadMcJson(Project project, boolean offline) throws IOException { | ||||
|  | @ -135,7 +140,7 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 
 | ||||
| 		Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); | ||||
| 
 | ||||
| 		if(extension.customManifest != null){ | ||||
| 		if (extension.customManifest != null) { | ||||
| 			ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); | ||||
| 			customVersion.id = minecraftVersion; | ||||
| 			customVersion.url = extension.customManifest; | ||||
|  | @ -143,7 +148,7 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 			project.getLogger().lifecycle("Using custom minecraft manifest"); | ||||
| 		} | ||||
| 
 | ||||
| 		if(!optionalVersion.isPresent()){ | ||||
| 		if (!optionalVersion.isPresent()) { | ||||
| 			optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -165,7 +170,6 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 		} else { | ||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadJars(Logger logger) throws IOException { | ||||
|  | @ -182,6 +186,7 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 
 | ||||
| 	private void mergeJars(Logger logger) throws IOException { | ||||
| 		logger.lifecycle(":merging jars"); | ||||
| 
 | ||||
| 		try (JarMerger jarMerger = new JarMerger(MINECRAFT_CLIENT_JAR, MINECRAFT_SERVER_JAR, MINECRAFT_MERGED_JAR)) { | ||||
| 			jarMerger.enableSyntheticParamsOffset(); | ||||
| 			jarMerger.merge(); | ||||
|  |  | |||
|  | @ -24,29 +24,52 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| import org.gradle.api.file.FileCollection; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.InputFiles; | ||||
| import org.gradle.api.tasks.OutputFile; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| public abstract class AbstractDecompileTask extends AbstractLoomTask { | ||||
|     private Object input; | ||||
|     private Object output; | ||||
|     private Object lineMapFile; | ||||
|     private Object libraries; | ||||
| 	private Object input; | ||||
| 	private Object output; | ||||
| 	private Object lineMapFile; | ||||
| 	private Object libraries; | ||||
| 
 | ||||
|     //@formatter:off | ||||
|     @InputFile | ||||
|     public File getInput() { return getProject().file(input); } | ||||
|     @OutputFile public File getOutput() { return getProject().file(output); } | ||||
|     @OutputFile public File getLineMapFile() { return getProject().file(lineMapFile); } | ||||
|     @InputFiles public FileCollection getLibraries() { return getProject().files(libraries); } | ||||
|     public void setInput(Object input) { this.input = input; } | ||||
|     public void setOutput(Object output) { this.output = output; } | ||||
|     public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } | ||||
|     public void setLibraries(Object libraries) { this.libraries = libraries; } | ||||
|     //@formatter:on | ||||
| 	@InputFile | ||||
| 	public File getInput() { | ||||
| 		return getProject().file(input); | ||||
| 	} | ||||
| 
 | ||||
| 	@OutputFile | ||||
| 	public File getOutput() { | ||||
| 		return getProject().file(output); | ||||
| 	} | ||||
| 
 | ||||
| 	@OutputFile | ||||
| 	public File getLineMapFile() { | ||||
| 		return getProject().file(lineMapFile); | ||||
| 	} | ||||
| 
 | ||||
| 	@InputFiles | ||||
| 	public FileCollection getLibraries() { | ||||
| 		return getProject().files(libraries); | ||||
| 	} | ||||
| 
 | ||||
| 	public void setInput(Object input) { | ||||
| 		this.input = input; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setOutput(Object output) { | ||||
| 		this.output = output; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setLineMapFile(Object lineMapFile) { | ||||
| 		this.lineMapFile = lineMapFile; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setLibraries(Object libraries) { | ||||
| 		this.libraries = libraries; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -27,9 +27,7 @@ package net.fabricmc.loom.task; | |||
| import org.gradle.api.DefaultTask; | ||||
| 
 | ||||
| public abstract class AbstractLoomTask extends DefaultTask { | ||||
| 
 | ||||
| 	public AbstractLoomTask() { | ||||
| 		setGroup("fabric"); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -24,14 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| import net.fabricmc.loom.util.OperatingSystem; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.JavaExec; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
|  | @ -41,99 +33,113 @@ import java.util.Collections; | |||
| import java.util.List; | ||||
| import java.util.function.Function; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.JavaExec; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.util.MinecraftVersionInfo; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| 
 | ||||
| public abstract class AbstractRunTask extends JavaExec { | ||||
|     private final Function<Project, RunConfig> configProvider; | ||||
|     private RunConfig config; | ||||
| 	private final Function<Project, RunConfig> configProvider; | ||||
| 	private RunConfig config; | ||||
| 
 | ||||
|     public AbstractRunTask(Function<Project, RunConfig> config) { | ||||
|         super(); | ||||
|         setGroup("fabric"); | ||||
|         this.configProvider = config; | ||||
|     } | ||||
| 	public AbstractRunTask(Function<Project, RunConfig> config) { | ||||
| 		super(); | ||||
| 		setGroup("fabric"); | ||||
| 		this.configProvider = config; | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void exec() { | ||||
|         if (config == null) { | ||||
|             config = configProvider.apply(getProject()); | ||||
|         } | ||||
| 	@Override | ||||
| 	public void exec() { | ||||
| 		if (config == null) { | ||||
| 			config = configProvider.apply(getProject()); | ||||
| 		} | ||||
| 
 | ||||
|         LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
|         MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo; | ||||
|         MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MinecraftVersionInfo minecraftVersionInfo = extension.getMinecraftProvider().versionInfo; | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
|         List<String> libs = new ArrayList<>(); | ||||
|         for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) { | ||||
|             libs.add(file.getAbsolutePath()); | ||||
|         } | ||||
|         for (Path file : extension.getUnmappedMods()) { | ||||
|             if (Files.isRegularFile(file)) { | ||||
|                 libs.add(file.toFile().getAbsolutePath()); | ||||
|             } | ||||
|         } | ||||
| 		List<String> libs = new ArrayList<>(); | ||||
| 
 | ||||
|         classpath(libs); | ||||
|         List<String> argsSplit = new ArrayList<>(); | ||||
|         String[] args = config.programArgs.split(" "); | ||||
|         int partPos = -1; | ||||
|         for (int i = 0; i < args.length; i++) { | ||||
|             if (partPos < 0) { | ||||
|                 if (args[i].startsWith("\"")) { | ||||
|                     if (args[i].endsWith("\"")) { | ||||
|                         argsSplit.add(args[i].substring(1, args[i].length() - 1)); | ||||
|                     } else { | ||||
|                         partPos = i; | ||||
|                     } | ||||
|                 } else { | ||||
|                     argsSplit.add(args[i]); | ||||
|                 } | ||||
|             } else if (args[i].endsWith("\"")) { | ||||
|                 StringBuilder builder = new StringBuilder(args[partPos].substring(1)); | ||||
|                 for (int j = partPos + 1; j < i; j++) { | ||||
|                     builder.append(" ").append(args[j]); | ||||
|                 } | ||||
|                 builder.append(" ").append(args[i], 0, args[i].length() - 1); | ||||
|                 argsSplit.add(builder.toString()); | ||||
|                 partPos = -1; | ||||
|             } | ||||
|         } | ||||
| 		for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) { | ||||
| 			libs.add(file.getAbsolutePath()); | ||||
| 		} | ||||
| 
 | ||||
|         args(argsSplit); | ||||
|         setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); | ||||
| 		for (Path file : extension.getUnmappedMods()) { | ||||
| 			if (Files.isRegularFile(file)) { | ||||
| 				libs.add(file.toFile().getAbsolutePath()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|         super.exec(); | ||||
|     } | ||||
| 		classpath(libs); | ||||
| 		List<String> argsSplit = new ArrayList<>(); | ||||
| 		String[] args = config.programArgs.split(" "); | ||||
| 		int partPos = -1; | ||||
| 
 | ||||
|     @Override | ||||
|     public void setWorkingDir(File dir) { | ||||
|         if (config == null) { | ||||
|             config = configProvider.apply(getProject()); | ||||
|         } | ||||
| 		for (int i = 0; i < args.length; i++) { | ||||
| 			if (partPos < 0) { | ||||
| 				if (args[i].startsWith("\"")) { | ||||
| 					if (args[i].endsWith("\"")) { | ||||
| 						argsSplit.add(args[i].substring(1, args[i].length() - 1)); | ||||
| 					} else { | ||||
| 						partPos = i; | ||||
| 					} | ||||
| 				} else { | ||||
| 					argsSplit.add(args[i]); | ||||
| 				} | ||||
| 			} else if (args[i].endsWith("\"")) { | ||||
| 				StringBuilder builder = new StringBuilder(args[partPos].substring(1)); | ||||
| 
 | ||||
|         if(!dir.exists()){ | ||||
|             dir.mkdirs(); | ||||
|         } | ||||
|         super.setWorkingDir(dir); | ||||
|     } | ||||
| 				for (int j = partPos + 1; j < i; j++) { | ||||
| 					builder.append(" ").append(args[j]); | ||||
| 				} | ||||
| 
 | ||||
|     @Override | ||||
|     public String getMain() { | ||||
|         if (config == null) { | ||||
|             config = configProvider.apply(getProject()); | ||||
|         } | ||||
| 				builder.append(" ").append(args[i], 0, args[i].length() - 1); | ||||
| 				argsSplit.add(builder.toString()); | ||||
| 				partPos = -1; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|         return config.mainClass; | ||||
|     } | ||||
| 		args(argsSplit); | ||||
| 		setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); | ||||
| 
 | ||||
|     @Override | ||||
|     public List<String> getJvmArgs() { | ||||
|         if (config == null) { | ||||
|             config = configProvider.apply(getProject()); | ||||
|         } | ||||
| 		super.exec(); | ||||
| 	} | ||||
| 
 | ||||
|         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; | ||||
|     } | ||||
| 	@Override | ||||
| 	public void setWorkingDir(File dir) { | ||||
| 		if (config == null) { | ||||
| 			config = configProvider.apply(getProject()); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!dir.exists()) { | ||||
| 			dir.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		super.setWorkingDir(dir); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getMain() { | ||||
| 		if (config == null) { | ||||
| 			config = configProvider.apply(getProject()); | ||||
| 		} | ||||
| 
 | ||||
| 		return config.mainClass; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public List<String> getJvmArgs() { | ||||
| 		if (config == null) { | ||||
| 			config = configProvider.apply(getProject()); | ||||
| 		} | ||||
| 
 | ||||
| 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		List<String> superArgs = super.getJvmArgs(); | ||||
| 		List<String> args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList()); | ||||
| 		args.addAll(Arrays.asList(config.vmArgs.split(" "))); | ||||
| 		return args; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,26 +24,28 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| 
 | ||||
| public class CleanLoomBinaries extends AbstractLoomTask { | ||||
|     @TaskAction | ||||
|     public void run() { | ||||
|         Project project = this.getProject(); | ||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|         extension.getMinecraftProvider().getMergedJar().delete(); | ||||
|         extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||
|         extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||
| 	    try { | ||||
| 		    FileUtils.deleteDirectory(extension.getNativesDirectory()); | ||||
| 		    FileUtils.deleteDirectory(extension.getNativesJarStore()); | ||||
| 	    } catch (IOException e) { | ||||
| 		    e.printStackTrace(); | ||||
| 	    } | ||||
|     } | ||||
| 	@TaskAction | ||||
| 	public void run() { | ||||
| 		Project project = this.getProject(); | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		extension.getMinecraftProvider().getMergedJar().delete(); | ||||
| 		extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||
| 		extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||
| 
 | ||||
| 		try { | ||||
| 			FileUtils.deleteDirectory(extension.getNativesDirectory()); | ||||
| 			FileUtils.deleteDirectory(extension.getNativesJarStore()); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,27 +24,29 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.DeletingFileVisitor; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.DeletingFileVisitor; | ||||
| 
 | ||||
| public class CleanLoomMappings extends AbstractLoomTask { | ||||
|     @TaskAction | ||||
|     public void run() { | ||||
|         Project project = this.getProject(); | ||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|         extension.getMappingsProvider().MAPPINGS_TINY.delete(); | ||||
|         extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete(); | ||||
|         extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||
|         extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||
|         try { | ||||
|             Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
| 	@TaskAction | ||||
| 	public void run() { | ||||
| 		Project project = this.getProject(); | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		extension.getMappingsProvider().MAPPINGS_TINY.delete(); | ||||
| 		extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete(); | ||||
| 		extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); | ||||
| 		extension.getMinecraftMappedProvider().getMappedJar().delete(); | ||||
| 
 | ||||
| 		try { | ||||
| 			Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,13 +24,14 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||
| 
 | ||||
| public class DownloadAssetsTask extends AbstractLoomTask { | ||||
| 	@TaskAction | ||||
|  |  | |||
|  | @ -36,18 +36,18 @@ import org.gradle.process.JavaExecSpec; | |||
|  * Simple trait like interface for a Task that wishes to execute a java process | ||||
|  * with the classpath of the gradle plugin plus groovy. | ||||
|  * | ||||
|  * Created by covers1624 on 11/02/19. | ||||
|  * <p>Created by covers1624 on 11/02/19. | ||||
|  */ | ||||
| public interface ForkingJavaExecTask extends Task { | ||||
| 	default ExecResult javaexec(Action<? super JavaExecSpec> action) { | ||||
| 		ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations(); | ||||
| 		DependencyHandler handler = getProject().getDependencies(); | ||||
| 		FileCollection classpath = configurations.getByName("classpath")// | ||||
| 				.plus(configurations.detachedConfiguration(handler.localGroovy())); | ||||
| 
 | ||||
|     default ExecResult javaexec(Action<? super JavaExecSpec> action) { | ||||
|         ConfigurationContainer configurations = getProject().getBuildscript().getConfigurations(); | ||||
|         DependencyHandler handler = getProject().getDependencies(); | ||||
|         FileCollection classpath = configurations.getByName("classpath")// | ||||
|                 .plus(configurations.detachedConfiguration(handler.localGroovy())); | ||||
|         return getProject().javaexec(spec -> { | ||||
|             spec.classpath(classpath); | ||||
|             action.execute(spec); | ||||
|         }); | ||||
|     } | ||||
| 		return getProject().javaexec(spec -> { | ||||
| 			spec.classpath(classpath); | ||||
| 			action.execute(spec); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,33 +24,37 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| 
 | ||||
| public class GenEclipseRunsTask extends AbstractLoomTask { | ||||
| 	@TaskAction | ||||
| 	public void genRuns() throws IOException { | ||||
| 		File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch"); | ||||
| 		File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch"); | ||||
| 
 | ||||
|     @TaskAction | ||||
|     public void genRuns() throws IOException { | ||||
| 	    File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch"); | ||||
| 	    File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch"); | ||||
| 		String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||
| 		String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||
| 
 | ||||
| 	    String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||
| 	    String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | ||||
| 		if (!clientRunConfigs.exists()) { | ||||
| 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | ||||
| 		} | ||||
| 
 | ||||
| 	    if(!clientRunConfigs.exists()) | ||||
| 		    FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | ||||
| 	    if(!serverRunConfigs.exists()) | ||||
| 		    FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | ||||
| 		if (!serverRunConfigs.exists()) { | ||||
| 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | ||||
| 		} | ||||
| 
 | ||||
| 	    File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir); | ||||
| 	    if(!runDir.exists()) | ||||
| 		    runDir.mkdirs(); | ||||
|     } | ||||
| 		File runDir = new File(getProject().getRootDir(), this.getProject().getExtensions().getByType(LoomGradleExtension.class).runDir); | ||||
| 
 | ||||
| 		if (!runDir.exists()) { | ||||
| 			runDir.mkdirs(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,15 +24,8 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.AbstractPlugin; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| import org.w3c.dom.Document; | ||||
| import org.w3c.dom.Element; | ||||
| import org.w3c.dom.NodeList; | ||||
| import org.xml.sax.SAXException; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import javax.xml.parsers.DocumentBuilder; | ||||
| import javax.xml.parsers.DocumentBuilderFactory; | ||||
|  | @ -43,18 +36,28 @@ import javax.xml.transform.TransformerException; | |||
| import javax.xml.transform.TransformerFactory; | ||||
| import javax.xml.transform.dom.DOMSource; | ||||
| import javax.xml.transform.stream.StreamResult; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.w3c.dom.Document; | ||||
| import org.w3c.dom.Element; | ||||
| import org.w3c.dom.NodeList; | ||||
| import org.xml.sax.SAXException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import net.fabricmc.loom.AbstractPlugin; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| 
 | ||||
| public class GenIdeaProjectTask extends AbstractLoomTask { | ||||
| 
 | ||||
| 	@TaskAction | ||||
| 	public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { | ||||
| 		Project project = this.getProject(); | ||||
| 
 | ||||
| 		//Only generate the idea runs on the root project | ||||
| 		if(!AbstractPlugin.isRootProject(project)){ | ||||
| 		if (!AbstractPlugin.isRootProject(project)) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		project.getLogger().lifecycle(":Building idea workspace"); | ||||
| 
 | ||||
|  | @ -65,8 +68,10 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | |||
| 
 | ||||
| 		NodeList list = doc.getElementsByTagName("component"); | ||||
| 		Element runManager = null; | ||||
| 
 | ||||
| 		for (int i = 0; i < list.getLength(); i++) { | ||||
| 			Element element = (Element) list.item(i); | ||||
| 
 | ||||
| 			if (element.getAttribute("name").equals("RunManager")) { | ||||
| 				runManager = element; | ||||
| 				break; | ||||
|  | @ -89,6 +94,7 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | |||
| 		transformer.transform(source, result); | ||||
| 
 | ||||
| 		File runDir = new File(getProject().getRootDir(), extension.runDir); | ||||
| 
 | ||||
| 		if (!runDir.exists()) { | ||||
| 			runDir.mkdirs(); | ||||
| 		} | ||||
|  |  | |||
|  | @ -24,81 +24,85 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.RunConfig; | ||||
| 
 | ||||
| //Recommended vscode plugins: | ||||
| // https://marketplace.visualstudio.com/items?itemName=redhat.java | ||||
| // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug | ||||
| // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack | ||||
| public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||
| 	@TaskAction | ||||
| 	public void genRuns() { | ||||
| 		LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		File projectDir = getProject().file(".vscode"); | ||||
| 
 | ||||
|     @TaskAction | ||||
|     public void genRuns() { | ||||
|         LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
|         File projectDir = getProject().file(".vscode"); | ||||
|         if (!projectDir.exists()) { | ||||
|             projectDir.mkdir(); | ||||
|         } | ||||
|         File launchJson = new File(projectDir, "launch.json"); | ||||
|         if (launchJson.exists()) { | ||||
|             launchJson.delete(); | ||||
|         } | ||||
| 		if (!projectDir.exists()) { | ||||
| 			projectDir.mkdir(); | ||||
| 		} | ||||
| 
 | ||||
|         VsCodeLaunch launch = new VsCodeLaunch(); | ||||
|         launch.add(RunConfig.clientRunConfig(getProject())); | ||||
|         launch.add(RunConfig.serverRunConfig(getProject())); | ||||
| 		File launchJson = new File(projectDir, "launch.json"); | ||||
| 
 | ||||
|         Gson gson = new GsonBuilder().setPrettyPrinting().create(); | ||||
|         String json = gson.toJson(launch); | ||||
| 		if (launchJson.exists()) { | ||||
| 			launchJson.delete(); | ||||
| 		} | ||||
| 
 | ||||
|         try { | ||||
|             FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException("Failed to write launch.json", e); | ||||
|         } | ||||
| 		VsCodeLaunch launch = new VsCodeLaunch(); | ||||
| 		launch.add(RunConfig.clientRunConfig(getProject())); | ||||
| 		launch.add(RunConfig.serverRunConfig(getProject())); | ||||
| 
 | ||||
|         File runDir = new File(getProject().getRootDir(), extension.runDir); | ||||
|         if (!runDir.exists()) { | ||||
|             runDir.mkdirs(); | ||||
|         } | ||||
|     } | ||||
| 		Gson gson = new GsonBuilder().setPrettyPrinting().create(); | ||||
| 		String json = gson.toJson(launch); | ||||
| 
 | ||||
|     private static class VsCodeLaunch { | ||||
|         public String version = "0.2.0"; | ||||
|         public List<VsCodeConfiguration> configurations = new ArrayList<>(); | ||||
| 		try { | ||||
| 			FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Failed to write launch.json", e); | ||||
| 		} | ||||
| 
 | ||||
|         public void add(RunConfig runConfig) { | ||||
|             configurations.add(new VsCodeConfiguration(runConfig)); | ||||
|         } | ||||
|     } | ||||
| 		File runDir = new File(getProject().getRootDir(), extension.runDir); | ||||
| 
 | ||||
|     private static class VsCodeConfiguration { | ||||
|         public String type = "java"; | ||||
|         public String name; | ||||
|         public String request = "launch"; | ||||
|         public String cwd = "${workspaceFolder}/run"; | ||||
|         public String console = "internalConsole"; | ||||
|         public boolean stopOnEntry = false; | ||||
|         public String mainClass; | ||||
|         public String vmArgs; | ||||
|         public String args; | ||||
| 		if (!runDir.exists()) { | ||||
| 			runDir.mkdirs(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|         public VsCodeConfiguration(RunConfig runConfig) { | ||||
|             this.name = runConfig.configName; | ||||
|             this.mainClass = runConfig.mainClass; | ||||
|             this.vmArgs = runConfig.vmArgs; | ||||
|             this.args = runConfig.programArgs; | ||||
|         } | ||||
|     } | ||||
| 	private static class VsCodeLaunch { | ||||
| 		public String version = "0.2.0"; | ||||
| 		public List<VsCodeConfiguration> configurations = new ArrayList<>(); | ||||
| 
 | ||||
| 		public void add(RunConfig runConfig) { | ||||
| 			configurations.add(new VsCodeConfiguration(runConfig)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static class VsCodeConfiguration { | ||||
| 		public String type = "java"; | ||||
| 		public String name; | ||||
| 		public String request = "launch"; | ||||
| 		public String cwd = "${workspaceFolder}/run"; | ||||
| 		public String console = "internalConsole"; | ||||
| 		public boolean stopOnEntry = false; | ||||
| 		public String mainClass; | ||||
| 		public String vmArgs; | ||||
| 		public String args; | ||||
| 
 | ||||
| 		VsCodeConfiguration(RunConfig runConfig) { | ||||
| 			this.name = runConfig.configName; | ||||
| 			this.mainClass = runConfig.mainClass; | ||||
| 			this.vmArgs = runConfig.vmArgs; | ||||
| 			this.args = runConfig.programArgs; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,10 +24,12 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.Version; | ||||
| import net.fabricmc.mappings.*; | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.cadixdev.lorenz.MappingSet; | ||||
| import org.cadixdev.lorenz.io.MappingsReader; | ||||
| import org.cadixdev.mercury.Mercury; | ||||
|  | @ -35,149 +37,147 @@ import org.cadixdev.mercury.remapper.MercuryRemapper; | |||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.Version; | ||||
| import net.fabricmc.mappings.ClassEntry; | ||||
| import net.fabricmc.mappings.EntryTriple; | ||||
| import net.fabricmc.mappings.FieldEntry; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import net.fabricmc.mappings.MethodEntry; | ||||
| 
 | ||||
| public class MigrateMappingsTask extends AbstractLoomTask { | ||||
|     @TaskAction | ||||
|     public void doTask() throws Throwable { | ||||
|         Project project = getProject(); | ||||
|         LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|         Map<String, ?> properties = project.getProperties(); | ||||
| 	@TaskAction | ||||
| 	public void doTask() throws Throwable { | ||||
| 		Project project = getProject(); | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		Map<String, ?> properties = project.getProperties(); | ||||
| 
 | ||||
|         project.getLogger().lifecycle(":loading mappings"); | ||||
| 		project.getLogger().lifecycle(":loading mappings"); | ||||
| 
 | ||||
|         File mappingsFile = null; | ||||
| 		File mappingsFile = null; | ||||
| 
 | ||||
|         if (properties.containsKey("targetMappingsFile")) { | ||||
|             mappingsFile = new File((String) properties.get("targetMappingsFile")); | ||||
|         } else if (properties.containsKey("targetMappingsArtifact")) { | ||||
|             String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":"); | ||||
|             if (artifactName.length != 3) { | ||||
|                 throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact")); | ||||
|             } | ||||
| 		if (properties.containsKey("targetMappingsFile")) { | ||||
| 			mappingsFile = new File((String) properties.get("targetMappingsFile")); | ||||
| 		} else if (properties.containsKey("targetMappingsArtifact")) { | ||||
| 			String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":"); | ||||
| 
 | ||||
|             String mappingsName = artifactName[0] + "." + artifactName[1]; | ||||
| 			if (artifactName.length != 3) { | ||||
| 				throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact")); | ||||
| 			} | ||||
| 
 | ||||
|             Version v = new Version(artifactName[2]); | ||||
|             String minecraftVersion = v.getMinecraftVersion(); | ||||
|             String mappingsVersion = v.getMappingsVersion(); | ||||
| 			String mappingsName = artifactName[0] + "." + artifactName[1]; | ||||
| 
 | ||||
|             mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion); | ||||
|         } | ||||
| 			Version v = new Version(artifactName[2]); | ||||
| 			String minecraftVersion = v.getMinecraftVersion(); | ||||
| 			String mappingsVersion = v.getMappingsVersion(); | ||||
| 
 | ||||
|         if (mappingsFile == null || !mappingsFile.exists()) { | ||||
|             throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null")); | ||||
|         } | ||||
| 			mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion); | ||||
| 		} | ||||
| 
 | ||||
|         if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) { | ||||
|             throw new RuntimeException("Must specify input and output dir!"); | ||||
|         } | ||||
| 		if (mappingsFile == null || !mappingsFile.exists()) { | ||||
| 			throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null")); | ||||
| 		} | ||||
| 
 | ||||
|         File inputDir = new File((String) properties.get("inputDir")); | ||||
|         File outputDir = new File((String) properties.get("outputDir")); | ||||
| 		if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) { | ||||
| 			throw new RuntimeException("Must specify input and output dir!"); | ||||
| 		} | ||||
| 
 | ||||
|         if (!inputDir.exists() || !inputDir.isDirectory()) { | ||||
|             throw new RuntimeException("Could not find input directory: " + inputDir); | ||||
|         } | ||||
| 		File inputDir = new File((String) properties.get("inputDir")); | ||||
| 		File outputDir = new File((String) properties.get("outputDir")); | ||||
| 
 | ||||
|         if (!outputDir.exists()) { | ||||
|             if (!outputDir.mkdirs()) { | ||||
|                 throw new RuntimeException("Could not create output directory:"  + outputDir); | ||||
|             } | ||||
|         } | ||||
| 		if (!inputDir.exists() || !inputDir.isDirectory()) { | ||||
| 			throw new RuntimeException("Could not find input directory: " + inputDir); | ||||
| 		} | ||||
| 
 | ||||
|         Mappings sourceMappings = extension.getMappingsProvider().getMappings(); | ||||
|         Mappings targetMappings; | ||||
| 		if (!outputDir.exists()) { | ||||
| 			if (!outputDir.mkdirs()) { | ||||
| 				throw new RuntimeException("Could not create output directory:" + outputDir); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|         try (FileInputStream stream = new FileInputStream(mappingsFile)) { | ||||
|             targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||
|         } | ||||
| 		Mappings sourceMappings = extension.getMappingsProvider().getMappings(); | ||||
| 		Mappings targetMappings; | ||||
| 
 | ||||
|         project.getLogger().lifecycle(":joining mappings"); | ||||
|         MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read(); | ||||
| 		try (FileInputStream stream = new FileInputStream(mappingsFile)) { | ||||
| 			targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||
| 		} | ||||
| 
 | ||||
|         project.getLogger().lifecycle(":remapping"); | ||||
|         Mercury mercury = new Mercury(); | ||||
| 		project.getLogger().lifecycle(":joining mappings"); | ||||
| 		MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read(); | ||||
| 
 | ||||
|         for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | ||||
|             mercury.getClassPath().add(file.toPath()); | ||||
|         } | ||||
| 		project.getLogger().lifecycle(":remapping"); | ||||
| 		Mercury mercury = new Mercury(); | ||||
| 
 | ||||
|         for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | ||||
|             mercury.getClassPath().add(file.toPath()); | ||||
|         } | ||||
| 		for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | ||||
| 			mercury.getClassPath().add(file.toPath()); | ||||
| 		} | ||||
| 
 | ||||
|         mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath()); | ||||
|         mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath()); | ||||
| 		for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | ||||
| 			mercury.getClassPath().add(file.toPath()); | ||||
| 		} | ||||
| 
 | ||||
|         mercury.getProcessors().add(MercuryRemapper.create(mappingSet)); | ||||
| 		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath()); | ||||
| 		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath()); | ||||
| 
 | ||||
|         try { | ||||
|             mercury.rewrite(inputDir.toPath(), outputDir.toPath()); | ||||
|         } catch (Exception e) { | ||||
|             project.getLogger().warn("Could not remap fully!", e); | ||||
|         } | ||||
| 		mercury.getProcessors().add(MercuryRemapper.create(mappingSet)); | ||||
| 
 | ||||
|         project.getLogger().lifecycle(":cleaning file descriptors"); | ||||
|         System.gc(); | ||||
|     } | ||||
| 		try { | ||||
| 			mercury.rewrite(inputDir.toPath(), outputDir.toPath()); | ||||
| 		} catch (Exception e) { | ||||
| 			project.getLogger().warn("Could not remap fully!", e); | ||||
| 		} | ||||
| 
 | ||||
|     public static class MappingsJoiner extends MappingsReader { | ||||
|         private final Mappings sourceMappings, targetMappings; | ||||
|         private final String fromNamespace, toNamespace; | ||||
| 		project.getLogger().lifecycle(":cleaning file descriptors"); | ||||
| 		System.gc(); | ||||
| 	} | ||||
| 
 | ||||
|         public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) { | ||||
|             this.sourceMappings = sourceMappings; | ||||
|             this.targetMappings = targetMappings; | ||||
|             this.fromNamespace = fromNamespace; | ||||
|             this.toNamespace = toNamespace; | ||||
|         } | ||||
| 	public static class MappingsJoiner extends MappingsReader { | ||||
| 		private final Mappings sourceMappings, targetMappings; | ||||
| 		private final String fromNamespace, toNamespace; | ||||
| 
 | ||||
|         @Override | ||||
|         public MappingSet read(MappingSet mappings) throws IOException { | ||||
|             Map<String, ClassEntry> targetClasses = new HashMap<>(); | ||||
|             Map<EntryTriple, FieldEntry> targetFields = new HashMap<>(); | ||||
|             Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>(); | ||||
| 		public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) { | ||||
| 			this.sourceMappings = sourceMappings; | ||||
| 			this.targetMappings = targetMappings; | ||||
| 			this.fromNamespace = fromNamespace; | ||||
| 			this.toNamespace = toNamespace; | ||||
| 		} | ||||
| 
 | ||||
|             targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c)); | ||||
|             targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c)); | ||||
|             targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c)); | ||||
| 		@Override | ||||
| 		public MappingSet read(MappingSet mappings) throws IOException { | ||||
| 			Map<String, ClassEntry> targetClasses = new HashMap<>(); | ||||
| 			Map<EntryTriple, FieldEntry> targetFields = new HashMap<>(); | ||||
| 			Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>(); | ||||
| 
 | ||||
|             for (ClassEntry entry : sourceMappings.getClassEntries()) { | ||||
|                 String from = entry.get(toNamespace); | ||||
|                 String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 			targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c)); | ||||
| 			targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c)); | ||||
| 			targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c)); | ||||
| 
 | ||||
|                 mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to); | ||||
|             } | ||||
| 			for (ClassEntry entry : sourceMappings.getClassEntries()) { | ||||
| 				String from = entry.get(toNamespace); | ||||
| 				String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 
 | ||||
|             for (FieldEntry entry : sourceMappings.getFieldEntries()) { | ||||
|                 EntryTriple fromEntry = entry.get(toNamespace); | ||||
|                 EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 				mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to); | ||||
| 			} | ||||
| 
 | ||||
|                 mappings.getOrCreateClassMapping(fromEntry.getOwner()) | ||||
|                         .getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()) | ||||
|                         .setDeobfuscatedName(toEntry.getName()); | ||||
|             } | ||||
| 			for (FieldEntry entry : sourceMappings.getFieldEntries()) { | ||||
| 				EntryTriple fromEntry = entry.get(toNamespace); | ||||
| 				EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 
 | ||||
|             for (MethodEntry entry : sourceMappings.getMethodEntries()) { | ||||
|                 EntryTriple fromEntry = entry.get(toNamespace); | ||||
|                 EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||
| 			} | ||||
| 
 | ||||
|                 mappings.getOrCreateClassMapping(fromEntry.getOwner()) | ||||
|                         .getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()) | ||||
|                         .setDeobfuscatedName(toEntry.getName()); | ||||
|             } | ||||
| 			for (MethodEntry entry : sourceMappings.getMethodEntries()) { | ||||
| 				EntryTriple fromEntry = entry.get(toNamespace); | ||||
| 				EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace); | ||||
| 
 | ||||
|             return mappings; | ||||
|         } | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||
| 			} | ||||
| 
 | ||||
|         @Override | ||||
|         public void close() throws IOException { | ||||
| 			return mappings; | ||||
| 		} | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 		@Override | ||||
| 		public void close() throws IOException { } | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,21 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.file.RegularFileProperty; | ||||
| import org.gradle.api.provider.Property; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| import org.gradle.jvm.tasks.Jar; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.util.GradleSupport; | ||||
|  | @ -33,21 +48,6 @@ import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | |||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| import net.fabricmc.tinyremapper.TinyUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.file.RegularFile; | ||||
| import org.gradle.api.file.RegularFileProperty; | ||||
| import org.gradle.api.provider.Property; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| import org.gradle.jvm.tasks.Jar; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| public class RemapJarTask extends Jar { | ||||
| 	private RegularFileProperty input; | ||||
|  | @ -86,6 +86,7 @@ public class RemapJarTask extends Jar { | |||
| 		TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper(); | ||||
| 
 | ||||
| 		remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)); | ||||
| 
 | ||||
| 		if (mixinMapFile.exists()) { | ||||
| 			remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM)); | ||||
| 		} | ||||
|  | @ -93,9 +94,11 @@ public class RemapJarTask extends Jar { | |||
| 		project.getLogger().lifecycle(":remapping " + input.getFileName()); | ||||
| 
 | ||||
| 		StringBuilder rc = new StringBuilder("Remap classpath: "); | ||||
| 
 | ||||
| 		for (Path p : classpath) { | ||||
| 			rc.append("\n - ").append(p.toString()); | ||||
| 		} | ||||
| 
 | ||||
| 		project.getLogger().debug(rc.toString()); | ||||
| 
 | ||||
| 		TinyRemapper remapper = remapperBuilder.build(); | ||||
|  |  | |||
|  | @ -24,51 +24,68 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||
| import net.fabricmc.loom.util.LineNumberRemapper; | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| import net.fabricmc.stitch.util.StitchUtil; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.OutputFile; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import net.fabricmc.loom.task.fernflower.FernFlowerTask; | ||||
| import net.fabricmc.loom.util.LineNumberRemapper; | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| import net.fabricmc.stitch.util.StitchUtil; | ||||
| 
 | ||||
| public class RemapLineNumbersTask extends AbstractLoomTask { | ||||
|     private Object input; | ||||
|     private Object output; | ||||
|     private Object lineMapFile; | ||||
| 	private Object input; | ||||
| 	private Object output; | ||||
| 	private Object lineMapFile; | ||||
| 
 | ||||
|     @TaskAction | ||||
|     public void doTask() throws Throwable { | ||||
|         Project project = getProject(); | ||||
| 	@TaskAction | ||||
| 	public void doTask() throws Throwable { | ||||
| 		Project project = getProject(); | ||||
| 
 | ||||
|         project.getLogger().lifecycle(":adjusting line numbers"); | ||||
|         LineNumberRemapper remapper = new LineNumberRemapper(); | ||||
|         remapper.readMappings(getLineMapFile()); | ||||
| 		project.getLogger().lifecycle(":adjusting line numbers"); | ||||
| 		LineNumberRemapper remapper = new LineNumberRemapper(); | ||||
| 		remapper.readMappings(getLineMapFile()); | ||||
| 
 | ||||
|         ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName()); | ||||
|         progressLogger.start("Adjusting line numbers", "linemap"); | ||||
| 		ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, FernFlowerTask.class.getName()); | ||||
| 		progressLogger.start("Adjusting line numbers", "linemap"); | ||||
| 
 | ||||
|         try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); | ||||
|              StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) { | ||||
|             remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
| 		try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(getInput(), true); StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(getOutput(), true)) { | ||||
| 			remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 
 | ||||
|         progressLogger.completed(); | ||||
|     } | ||||
| 		progressLogger.completed(); | ||||
| 	} | ||||
| 
 | ||||
|     //@formatter:off | ||||
|     @InputFile public File getInput() { return getProject().file(input); } | ||||
|     @InputFile public File getLineMapFile() { return getProject().file(lineMapFile); } | ||||
|     @OutputFile public File getOutput() { return getProject().file(output); } | ||||
|     public void setInput(Object input) { this.input = input; } | ||||
|     public void setLineMapFile(Object lineMapFile) { this.lineMapFile = lineMapFile; } | ||||
|     public void setOutput(Object output) { this.output = output; } | ||||
|     //@formatter:on | ||||
| 	@InputFile | ||||
| 	public File getInput() { | ||||
| 		return getProject().file(input); | ||||
| 	} | ||||
| 
 | ||||
| 	@InputFile | ||||
| 	public File getLineMapFile() { | ||||
| 		return getProject().file(lineMapFile); | ||||
| 	} | ||||
| 
 | ||||
| 	@OutputFile | ||||
| 	public File getOutput() { | ||||
| 		return getProject().file(output); | ||||
| 	} | ||||
| 
 | ||||
| 	public void setInput(Object input) { | ||||
| 		this.input = input; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setLineMapFile(Object lineMapFile) { | ||||
| 		this.lineMapFile = lineMapFile; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setOutput(Object output) { | ||||
| 		this.output = output; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,13 +24,14 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.SourceRemapper; | ||||
| import java.io.File; | ||||
| 
 | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.OutputFile; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import net.fabricmc.loom.util.SourceRemapper; | ||||
| 
 | ||||
| public class RemapSourcesJarTask extends AbstractLoomTask { | ||||
| 	private Object input; | ||||
|  | @ -42,13 +43,30 @@ public class RemapSourcesJarTask extends AbstractLoomTask { | |||
| 		SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); | ||||
| 	} | ||||
| 
 | ||||
| 	//@formatter:off | ||||
| 	@InputFile | ||||
| 	public File getInput() { return getProject().file(input); } | ||||
| 	@OutputFile public File getOutput() { return getProject().file(output == null ? input : output); } | ||||
| 	@Input public String getTargetNamespace() { return direction; } | ||||
| 	public void setInput(Object input) { this.input = input; } | ||||
| 	public void setOutput(Object output) { this.output = output; } | ||||
| 	public void setTargetNamespace(String value) { this.direction = value; } | ||||
| 	//@formatter:on | ||||
| 	public File getInput() { | ||||
| 		return getProject().file(input); | ||||
| 	} | ||||
| 
 | ||||
| 	@OutputFile | ||||
| 	public File getOutput() { | ||||
| 		return getProject().file(output == null ? input : output); | ||||
| 	} | ||||
| 
 | ||||
| 	@Input | ||||
| 	public String getTargetNamespace() { | ||||
| 		return direction; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setInput(Object input) { | ||||
| 		this.input = input; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setOutput(Object output) { | ||||
| 		this.output = output; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setTargetNamespace(String value) { | ||||
| 		this.direction = value; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,123 +24,140 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task.fernflower; | ||||
| 
 | ||||
| import net.fabricmc.loom.task.AbstractDecompileTask; | ||||
| import net.fabricmc.loom.task.ForkingJavaExecTask; | ||||
| import net.fabricmc.loom.util.ConsumingOutputStream; | ||||
| import org.gradle.api.file.FileCollection; | ||||
| import static java.text.MessageFormat.format; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Stack; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; | ||||
| import org.gradle.api.internal.project.ProjectInternal; | ||||
| import org.gradle.api.logging.LogLevel; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.OutputFile; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| import org.gradle.internal.logging.progress.ProgressLogger; | ||||
| import org.gradle.internal.logging.progress.ProgressLoggerFactory; | ||||
| import org.gradle.internal.service.ServiceRegistry; | ||||
| import org.gradle.process.ExecResult; | ||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import net.fabricmc.loom.task.AbstractDecompileTask; | ||||
| import net.fabricmc.loom.task.ForkingJavaExecTask; | ||||
| import net.fabricmc.loom.util.ConsumingOutputStream; | ||||
| import net.fabricmc.loom.util.OperatingSystem; | ||||
| import java.util.*; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import static java.text.MessageFormat.format; | ||||
| 
 | ||||
| /** | ||||
|  * Created by covers1624 on 9/02/19. | ||||
|  */ | ||||
| public class FernFlowerTask extends AbstractDecompileTask implements ForkingJavaExecTask { | ||||
| 	private boolean noFork = false; | ||||
| 	private int numThreads = Runtime.getRuntime().availableProcessors(); | ||||
| 
 | ||||
|     private boolean noFork = false; | ||||
|     private int numThreads = Runtime.getRuntime().availableProcessors(); | ||||
| 	@TaskAction | ||||
| 	public void doTask() throws Throwable { | ||||
| 		if (!OperatingSystem.is64Bit()) { | ||||
| 			throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements"); | ||||
| 		} | ||||
| 
 | ||||
|     @TaskAction | ||||
|     public void doTask() throws Throwable { | ||||
|     	if(!OperatingSystem.is64Bit()){ | ||||
|     		throw new UnsupportedOperationException("FernFlowerTask requires a 64bit JVM to run due to the memory requirements"); | ||||
| 	    } | ||||
| 		Map<String, Object> options = new HashMap<>(); | ||||
| 		options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1"); | ||||
| 		options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); | ||||
| 		options.put(IFernflowerPreferences.LOG_LEVEL, "trace"); | ||||
| 		getLogging().captureStandardOutput(LogLevel.LIFECYCLE); | ||||
| 
 | ||||
|         Map<String, Object> options = new HashMap<>(); | ||||
|         options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1"); | ||||
|         options.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); | ||||
|         options.put(IFernflowerPreferences.LOG_LEVEL, "trace"); | ||||
|         getLogging().captureStandardOutput(LogLevel.LIFECYCLE); | ||||
| 		List<String> args = new ArrayList<>(); | ||||
| 
 | ||||
|         List<String> args = new ArrayList<>(); | ||||
| 		options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); | ||||
| 		args.add(getInput().getAbsolutePath()); | ||||
| 		args.add("-o=" + getOutput().getAbsolutePath()); | ||||
| 
 | ||||
|         options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); | ||||
|         args.add(getInput().getAbsolutePath()); | ||||
|         args.add("-o=" + getOutput().getAbsolutePath()); | ||||
|         if (getLineMapFile() != null) { | ||||
|             args.add("-l=" + getLineMapFile().getAbsolutePath()); | ||||
|         } | ||||
|         args.add("-t=" + getNumThreads()); | ||||
| 		if (getLineMapFile() != null) { | ||||
| 			args.add("-l=" + getLineMapFile().getAbsolutePath()); | ||||
| 		} | ||||
| 
 | ||||
|         //TODO, Decompiler breaks on jemalloc, J9 module-info.class? | ||||
|         getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath())); | ||||
| 		args.add("-t=" + getNumThreads()); | ||||
| 
 | ||||
|         ServiceRegistry registry = ((ProjectInternal) getProject()).getServices(); | ||||
|         ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); | ||||
|         ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile"); | ||||
|         Supplier<ProgressLogger> loggerFactory = () -> { | ||||
|             ProgressLogger pl = factory.newOperation(getClass(), progressGroup); | ||||
|             pl.setDescription("decompile worker"); | ||||
|             pl.started(); | ||||
|             return pl; | ||||
|         }; | ||||
|         Stack<ProgressLogger> freeLoggers = new Stack<>(); | ||||
|         Map<String, ProgressLogger> inUseLoggers = new HashMap<>(); | ||||
| 		//TODO, Decompiler breaks on jemalloc, J9 module-info.class? | ||||
| 		getLibraries().forEach(f -> args.add("-e=" + f.getAbsolutePath())); | ||||
| 
 | ||||
|         progressGroup.started(); | ||||
|         ExecResult result = javaexec(spec -> { | ||||
|             spec.setMain(ForkedFFExecutor.class.getName()); | ||||
|             spec.jvmArgs("-Xms200m", "-Xmx3G"); | ||||
|             spec.setArgs(args); | ||||
|             spec.setErrorOutput(System.err); | ||||
|             spec.setStandardOutput(new ConsumingOutputStream(line -> { | ||||
|                 if (line.startsWith("Listening for transport") || !line.contains("::")) { | ||||
|                     System.out.println(line); | ||||
|                     return; | ||||
|                 } | ||||
| 		ServiceRegistry registry = ((ProjectInternal) getProject()).getServices(); | ||||
| 		ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); | ||||
| 		ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile"); | ||||
| 		Supplier<ProgressLogger> loggerFactory = () -> { | ||||
| 			ProgressLogger pl = factory.newOperation(getClass(), progressGroup); | ||||
| 			pl.setDescription("decompile worker"); | ||||
| 			pl.started(); | ||||
| 			return pl; | ||||
| 		}; | ||||
| 		Stack<ProgressLogger> freeLoggers = new Stack<>(); | ||||
| 		Map<String, ProgressLogger> inUseLoggers = new HashMap<>(); | ||||
| 
 | ||||
|                 int sepIdx = line.indexOf("::"); | ||||
|                 String id = line.substring(0, sepIdx).trim(); | ||||
|                 String data = line.substring(sepIdx + 2).trim(); | ||||
| 		progressGroup.started(); | ||||
| 		ExecResult result = javaexec(spec -> { | ||||
| 			spec.setMain(ForkedFFExecutor.class.getName()); | ||||
| 			spec.jvmArgs("-Xms200m", "-Xmx3G"); | ||||
| 			spec.setArgs(args); | ||||
| 			spec.setErrorOutput(System.err); | ||||
| 			spec.setStandardOutput(new ConsumingOutputStream(line -> { | ||||
| 				if (line.startsWith("Listening for transport") || !line.contains("::")) { | ||||
| 					System.out.println(line); | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
|                 ProgressLogger logger = inUseLoggers.get(id); | ||||
| 				int sepIdx = line.indexOf("::"); | ||||
| 				String id = line.substring(0, sepIdx).trim(); | ||||
| 				String data = line.substring(sepIdx + 2).trim(); | ||||
| 
 | ||||
|                 String[] segs = data.split(" "); | ||||
|                 if (segs[0].equals("waiting")) { | ||||
|                     if (logger != null) { | ||||
|                         logger.progress("Idle.."); | ||||
|                         inUseLoggers.remove(id); | ||||
|                         freeLoggers.push(logger); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (logger == null) { | ||||
|                         if (!freeLoggers.isEmpty()) { | ||||
|                             logger = freeLoggers.pop(); | ||||
|                         } else { | ||||
|                             logger = loggerFactory.get(); | ||||
|                         } | ||||
|                         inUseLoggers.put(id, logger); | ||||
|                     } | ||||
|                     logger.progress(data); | ||||
|                 } | ||||
|             })); | ||||
|         }); | ||||
|         inUseLoggers.values().forEach(ProgressLogger::completed); | ||||
|         freeLoggers.forEach(ProgressLogger::completed); | ||||
|         progressGroup.completed(); | ||||
| 				ProgressLogger logger = inUseLoggers.get(id); | ||||
| 
 | ||||
|         result.rethrowFailure(); | ||||
|         result.assertNormalExitValue(); | ||||
|     } | ||||
| 				String[] segs = data.split(" "); | ||||
| 
 | ||||
|     //@formatter:off | ||||
|     @Input public int getNumThreads() { return numThreads; } | ||||
|     @Input public boolean isNoFork() { return noFork; } | ||||
|     public void setNoFork(boolean noFork) { this.noFork = noFork; } | ||||
|     public void setNumThreads(int numThreads) { this.numThreads = numThreads; } | ||||
|     //@formatter:on | ||||
| 				if (segs[0].equals("waiting")) { | ||||
| 					if (logger != null) { | ||||
| 						logger.progress("Idle.."); | ||||
| 						inUseLoggers.remove(id); | ||||
| 						freeLoggers.push(logger); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if (logger == null) { | ||||
| 						if (!freeLoggers.isEmpty()) { | ||||
| 							logger = freeLoggers.pop(); | ||||
| 						} else { | ||||
| 							logger = loggerFactory.get(); | ||||
| 						} | ||||
| 
 | ||||
| 						inUseLoggers.put(id, logger); | ||||
| 					} | ||||
| 
 | ||||
| 					logger.progress(data); | ||||
| 				} | ||||
| 			})); | ||||
| 		}); | ||||
| 		inUseLoggers.values().forEach(ProgressLogger::completed); | ||||
| 		freeLoggers.forEach(ProgressLogger::completed); | ||||
| 		progressGroup.completed(); | ||||
| 
 | ||||
| 		result.rethrowFailure(); | ||||
| 		result.assertNormalExitValue(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Input | ||||
| 	public int getNumThreads() { | ||||
| 		return numThreads; | ||||
| 	} | ||||
| 
 | ||||
| 	@Input | ||||
| 	public boolean isNoFork() { | ||||
| 		return noFork; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setNoFork(boolean noFork) { | ||||
| 		this.noFork = noFork; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setNumThreads(int numThreads) { | ||||
| 		this.numThreads = numThreads; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,26 +24,29 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task.fernflower; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.util.InterpreterUtil; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipFile; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.util.InterpreterUtil; | ||||
| 
 | ||||
| public class FernFlowerUtils { | ||||
| 	public static byte[] getBytecode(String externalPath, String internalPath) throws IOException { | ||||
| 	    File file = new File(externalPath); | ||||
| 	    if (internalPath == null) { | ||||
| 	        return InterpreterUtil.getBytes(file); | ||||
| 	    } else { | ||||
| 	        try (ZipFile archive = new ZipFile(file)) { | ||||
| 	            ZipEntry entry = archive.getEntry(internalPath); | ||||
| 	            if (entry == null) { | ||||
| 	                throw new IOException("Entry not found: " + internalPath); | ||||
| 	            } | ||||
| 	            return InterpreterUtil.getBytes(archive, entry); | ||||
| 	        } | ||||
| 	    } | ||||
| 		File file = new File(externalPath); | ||||
| 
 | ||||
| 		if (internalPath == null) { | ||||
| 			return InterpreterUtil.getBytes(file); | ||||
| 		} else { | ||||
| 			try (ZipFile archive = new ZipFile(file)) { | ||||
| 				ZipEntry entry = archive.getEntry(internalPath); | ||||
| 
 | ||||
| 				if (entry == null) { | ||||
| 					throw new IOException("Entry not found: " + internalPath); | ||||
| 				} | ||||
| 
 | ||||
| 				return InterpreterUtil.getBytes(archive, entry); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,82 +24,92 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task.fernflower; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.main.Fernflower; | ||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||
| import org.jetbrains.java.decompiler.main.extern.IResultSaver; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.*; | ||||
| 
 | ||||
| /** | ||||
|  * Entry point for Forked FernFlower task. | ||||
|  * Takes one parameter, a single file, each line is treated as command line input. | ||||
|  * Forces one input file. | ||||
|  * Forces one output file using '-o=/path/to/output' | ||||
|  * | ||||
|  * Created by covers1624 on 11/02/19. | ||||
|  */ | ||||
| public class ForkedFFExecutor { | ||||
| 	public static void main(String[] args) throws IOException { | ||||
| 		Map<String, Object> options = new HashMap<>(); | ||||
| 		File input = null; | ||||
| 		File output = null; | ||||
| 		File lineMap = null; | ||||
| 		List<File> libraries = new ArrayList<>(); | ||||
| 		int numThreads = 0; | ||||
| 
 | ||||
|     public static void main(String[] args) throws IOException { | ||||
|         Map<String, Object> options = new HashMap<>(); | ||||
|         File input = null; | ||||
|         File output = null; | ||||
|         File lineMap = null; | ||||
|         List<File> libraries = new ArrayList<>(); | ||||
|         int numThreads = 0; | ||||
| 		boolean isOption = true; | ||||
| 
 | ||||
|         boolean isOption = true; | ||||
|         for (String arg : args) { | ||||
|             if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { | ||||
|                 String value = arg.substring(5); | ||||
|                 if ("true".equalsIgnoreCase(value)) { | ||||
|                     value = "1"; | ||||
|                 } else if ("false".equalsIgnoreCase(value)) { | ||||
|                     value = "0"; | ||||
|                 } | ||||
| 		for (String arg : args) { | ||||
| 			if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { | ||||
| 				String value = arg.substring(5); | ||||
| 
 | ||||
|                 options.put(arg.substring(1, 4), value); | ||||
|             } else { | ||||
|                 isOption = false; | ||||
|                 if (arg.startsWith("-e=")) { | ||||
|                     libraries.add(new File(arg.substring(3))); | ||||
|                 } else if (arg.startsWith("-o=")) { | ||||
|                     if (output != null) { | ||||
|                         throw new RuntimeException("Unable to set more than one output."); | ||||
|                     } | ||||
|                     output = new File(arg.substring(3)); | ||||
|                 } else if (arg.startsWith("-l=")) { | ||||
|                     if (lineMap != null) { | ||||
|                         throw new RuntimeException("Unable to set more than one lineMap file."); | ||||
|                     } | ||||
|                     lineMap = new File(arg.substring(3)); | ||||
|                 } else if (arg.startsWith("-t=")) { | ||||
|                     numThreads = Integer.parseInt(arg.substring(3)); | ||||
|                 } else { | ||||
|                     if (input != null) { | ||||
|                         throw new RuntimeException("Unable to set more than one input."); | ||||
|                     } | ||||
|                     input = new File(arg); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 				if ("true".equalsIgnoreCase(value)) { | ||||
| 					value = "1"; | ||||
| 				} else if ("false".equalsIgnoreCase(value)) { | ||||
| 					value = "0"; | ||||
| 				} | ||||
| 
 | ||||
|         Objects.requireNonNull(input, "Input not set."); | ||||
|         Objects.requireNonNull(output, "Output not set."); | ||||
| 				options.put(arg.substring(1, 4), value); | ||||
| 			} else { | ||||
| 				isOption = false; | ||||
| 
 | ||||
|         runFF(options, libraries, input, output, lineMap); | ||||
|     } | ||||
| 				if (arg.startsWith("-e=")) { | ||||
| 					libraries.add(new File(arg.substring(3))); | ||||
| 				} else if (arg.startsWith("-o=")) { | ||||
| 					if (output != null) { | ||||
| 						throw new RuntimeException("Unable to set more than one output."); | ||||
| 					} | ||||
| 
 | ||||
|     public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) { | ||||
|         IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); | ||||
|         IFernflowerLogger logger = new ThreadIDFFLogger(); | ||||
|         Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); | ||||
|         for (File library : libraries) { | ||||
|             ff.addLibrary(library); | ||||
|         } | ||||
|         ff.addSource(input); | ||||
|         ff.decompileContext(); | ||||
|     } | ||||
| 					output = new File(arg.substring(3)); | ||||
| 				} else if (arg.startsWith("-l=")) { | ||||
| 					if (lineMap != null) { | ||||
| 						throw new RuntimeException("Unable to set more than one lineMap file."); | ||||
| 					} | ||||
| 
 | ||||
| 					lineMap = new File(arg.substring(3)); | ||||
| 				} else if (arg.startsWith("-t=")) { | ||||
| 					numThreads = Integer.parseInt(arg.substring(3)); | ||||
| 				} else { | ||||
| 					if (input != null) { | ||||
| 						throw new RuntimeException("Unable to set more than one input."); | ||||
| 					} | ||||
| 
 | ||||
| 					input = new File(arg); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		Objects.requireNonNull(input, "Input not set."); | ||||
| 		Objects.requireNonNull(output, "Output not set."); | ||||
| 
 | ||||
| 		runFF(options, libraries, input, output, lineMap); | ||||
| 	} | ||||
| 
 | ||||
| 	public static void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap) { | ||||
| 		IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); | ||||
| 		IFernflowerLogger logger = new ThreadIDFFLogger(); | ||||
| 		Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); | ||||
| 
 | ||||
| 		for (File library : libraries) { | ||||
| 			ff.addLibrary(library); | ||||
| 		} | ||||
| 
 | ||||
| 		ff.addSource(input); | ||||
| 		ff.decompileContext(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -31,14 +31,9 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | |||
|  * Created by covers1624 on 11/02/19. | ||||
|  */ | ||||
| public class NoopFFLogger extends IFernflowerLogger { | ||||
| 	@Override | ||||
| 	public void writeMessage(String message, Severity severity) { } | ||||
| 
 | ||||
|     @Override | ||||
|     public void writeMessage(String message, Severity severity) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void writeMessage(String message, Severity severity, Throwable t) { | ||||
| 
 | ||||
|     } | ||||
| 	@Override | ||||
| 	public void writeMessage(String message, Severity severity, Throwable t) { } | ||||
| } | ||||
|  |  | |||
|  | @ -24,108 +24,108 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task.fernflower; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||
| 
 | ||||
| import java.io.PrintStream; | ||||
| import java.text.MessageFormat; | ||||
| import java.util.Stack; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; | ||||
| 
 | ||||
| /** | ||||
|  * This logger simply prints what each thread is doing | ||||
|  * to the console in a machine parsable way. | ||||
|  * | ||||
|  * Created by covers1624 on 11/02/19. | ||||
|  * <p>Created by covers1624 on 11/02/19. | ||||
|  */ | ||||
| public class ThreadIDFFLogger extends IFernflowerLogger { | ||||
| 	public final PrintStream stdOut; | ||||
| 	public final PrintStream stdErr; | ||||
| 
 | ||||
|     public final PrintStream stdOut; | ||||
|     public final PrintStream stdErr; | ||||
| 	private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); | ||||
| 	private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); | ||||
| 
 | ||||
|     private ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); | ||||
|     private ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); | ||||
| 	public ThreadIDFFLogger() { | ||||
| 		this(System.err, System.out); | ||||
| 	} | ||||
| 
 | ||||
|     public ThreadIDFFLogger() { | ||||
|         this(System.err, System.out); | ||||
|     } | ||||
| 	public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { | ||||
| 		this.stdOut = stdOut; | ||||
| 		this.stdErr = stdErr; | ||||
| 	} | ||||
| 
 | ||||
|     public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { | ||||
|         this.stdOut = stdOut; | ||||
|         this.stdErr = stdErr; | ||||
|     } | ||||
| 	@Override | ||||
| 	public void writeMessage(String message, Severity severity) { | ||||
| 		System.err.println(message); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void writeMessage(String message, Severity severity) { | ||||
|         System.err.println(message); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void writeMessage(String message, Severity severity, Throwable t) { | ||||
| 		System.err.println(message); | ||||
| 		t.printStackTrace(System.err); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void writeMessage(String message, Severity severity, Throwable t) { | ||||
|         System.err.println(message); | ||||
|         t.printStackTrace(System.err); | ||||
|     } | ||||
| 	private void print() { | ||||
| 		Thread thread = Thread.currentThread(); | ||||
| 		long id = thread.getId(); | ||||
| 
 | ||||
|     private void print() { | ||||
|         Thread thread = Thread.currentThread(); | ||||
|         long id = thread.getId(); | ||||
|         if (line.get().isEmpty()) { | ||||
|             System.out.println(MessageFormat.format("{0} :: waiting", id)); | ||||
|             return; | ||||
|         } | ||||
|         String line = this.line.get().peek(); | ||||
|         System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim()); | ||||
|     } | ||||
| 		if (line.get().isEmpty()) { | ||||
| 			System.out.println(MessageFormat.format("{0} :: waiting", id)); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
|     @Override | ||||
|     public void startReadingClass(String className) { | ||||
|         workingClass.get().push(className); | ||||
|         line.get().push("Decompiling " + className); | ||||
|         print(); | ||||
|     } | ||||
| 		String line = this.line.get().peek(); | ||||
| 		System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim()); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void startClass(String className) { | ||||
|         workingClass.get().push(className); | ||||
|         line.get().push("Decompiling " + className); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void startReadingClass(String className) { | ||||
| 		workingClass.get().push(className); | ||||
| 		line.get().push("Decompiling " + className); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void startMethod(String methodName) { | ||||
|         String className = workingClass.get().peek(); | ||||
|         line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" "))); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void startClass(String className) { | ||||
| 		workingClass.get().push(className); | ||||
| 		line.get().push("Decompiling " + className); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void endMethod() { | ||||
|         line.get().pop(); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void startMethod(String methodName) { | ||||
| 		String className = workingClass.get().peek(); | ||||
| 		line.get().push("Decompiling " + className + "." + methodName.substring(0, methodName.indexOf(" "))); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void endClass() { | ||||
|         line.get().pop(); | ||||
|         workingClass.get().pop(); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void endMethod() { | ||||
| 		line.get().pop(); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void startWriteClass(String className) { | ||||
|         line.get().push("Writing " + className); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void endClass() { | ||||
| 		line.get().pop(); | ||||
| 		workingClass.get().pop(); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void endWriteClass() { | ||||
|         line.get().pop(); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void startWriteClass(String className) { | ||||
| 		line.get().push("Writing " + className); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void endReadingClass() { | ||||
|         line.get().pop(); | ||||
|         workingClass.get().pop(); | ||||
|         print(); | ||||
|     } | ||||
| 	@Override | ||||
| 	public void endWriteClass() { | ||||
| 		line.get().pop(); | ||||
| 		print(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void endReadingClass() { | ||||
| 		line.get().pop(); | ||||
| 		workingClass.get().pop(); | ||||
| 		print(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,11 +24,11 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task.fernflower; | ||||
| 
 | ||||
| import net.fabricmc.fernflower.api.IFabricResultSaver; | ||||
| import org.jetbrains.java.decompiler.main.DecompilerContext; | ||||
| import org.jetbrains.java.decompiler.main.extern.IResultSaver; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.io.File; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.FileWriter; | ||||
| import java.io.IOException; | ||||
| import java.io.PrintWriter; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | @ -42,108 +42,136 @@ import java.util.jar.Manifest; | |||
| import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipOutputStream; | ||||
| 
 | ||||
| import org.jetbrains.java.decompiler.main.DecompilerContext; | ||||
| import org.jetbrains.java.decompiler.main.extern.IResultSaver; | ||||
| 
 | ||||
| import net.fabricmc.fernflower.api.IFabricResultSaver; | ||||
| 
 | ||||
| /** | ||||
|  * Created by covers1624 on 18/02/19. | ||||
|  */ | ||||
| public class ThreadSafeResultSaver implements IResultSaver, IFabricResultSaver { | ||||
|     private final Supplier<File> output; | ||||
|     private final Supplier<File> lineMapFile; | ||||
| 	private final Supplier<File> output; | ||||
| 	private final Supplier<File> lineMapFile; | ||||
| 
 | ||||
|     public Map<String, ZipOutputStream> outputStreams = new HashMap<>(); | ||||
|     public Map<String, ExecutorService> saveExecutors = new HashMap<>(); | ||||
|     public PrintWriter lineMapWriter; | ||||
| 	public Map<String, ZipOutputStream> outputStreams = new HashMap<>(); | ||||
| 	public Map<String, ExecutorService> saveExecutors = new HashMap<>(); | ||||
| 	public PrintWriter lineMapWriter; | ||||
| 
 | ||||
|     public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) { | ||||
|         this.output = output; | ||||
|         this.lineMapFile = lineMapFile; | ||||
|     } | ||||
| 	public ThreadSafeResultSaver(Supplier<File> output, Supplier<File> lineMapFile) { | ||||
| 		this.output = output; | ||||
| 		this.lineMapFile = lineMapFile; | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void createArchive(String path, String archiveName, Manifest manifest) { | ||||
|         String key = path + "/" + archiveName; | ||||
|         File file = output.get(); | ||||
|         try { | ||||
|             FileOutputStream fos = new FileOutputStream(file); | ||||
|             ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest); | ||||
|             outputStreams.put(key, zos); | ||||
|             saveExecutors.put(key, Executors.newSingleThreadExecutor()); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException("Unable to create archive: " + file, e); | ||||
|         } | ||||
|         if (lineMapFile.get() != null) { | ||||
|             try { | ||||
|                 lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get())); | ||||
|             } catch (IOException e) { | ||||
|                 throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 	@Override | ||||
| 	public void createArchive(String path, String archiveName, Manifest manifest) { | ||||
| 		String key = path + "/" + archiveName; | ||||
| 		File file = output.get(); | ||||
| 
 | ||||
|     @Override | ||||
|     public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { | ||||
|         this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null); | ||||
|     } | ||||
| 		try { | ||||
| 			FileOutputStream fos = new FileOutputStream(file); | ||||
| 			ZipOutputStream zos = manifest == null ? new ZipOutputStream(fos) : new JarOutputStream(fos, manifest); | ||||
| 			outputStreams.put(key, zos); | ||||
| 			saveExecutors.put(key, Executors.newSingleThreadExecutor()); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Unable to create archive: " + file, e); | ||||
| 		} | ||||
| 
 | ||||
|     @Override | ||||
|     public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) { | ||||
|         String key = path + "/" + archiveName; | ||||
|         ExecutorService executor = saveExecutors.get(key); | ||||
|         executor.submit(() -> { | ||||
|             ZipOutputStream zos = outputStreams.get(key); | ||||
|             try { | ||||
|                 zos.putNextEntry(new ZipEntry(entryName)); | ||||
|                 if (content != null) { | ||||
|                     zos.write(content.getBytes(StandardCharsets.UTF_8)); | ||||
|                 } | ||||
|             } catch (IOException e) { | ||||
|                 DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e); | ||||
|             } | ||||
|             if (mapping != null && lineMapWriter != null) { | ||||
|                 int maxLine = 0; | ||||
|                 int maxLineDest = 0; | ||||
|                 StringBuilder builder = new StringBuilder(); | ||||
|                 for (int i = 0; i < mapping.length; i += 2) { | ||||
|                     maxLine = Math.max(maxLine, mapping[i]); | ||||
|                     maxLineDest = Math.max(maxLineDest, mapping[i + 1]); | ||||
|                     builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n"); | ||||
|                 } | ||||
|                 lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest); | ||||
|                 lineMapWriter.println(builder.toString()); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 		if (lineMapFile.get() != null) { | ||||
| 			try { | ||||
| 				lineMapWriter = new PrintWriter(new FileWriter(lineMapFile.get())); | ||||
| 			} catch (IOException e) { | ||||
| 				throw new RuntimeException("Unable to create line mapping file: " + lineMapFile.get(), e); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void closeArchive(String path, String archiveName) { | ||||
|         String key = path + "/" + archiveName; | ||||
|         ExecutorService executor = saveExecutors.get(key); | ||||
|         Future<?> closeFuture = executor.submit(() -> { | ||||
|             ZipOutputStream zos = outputStreams.get(key); | ||||
|             try { | ||||
|                 zos.close(); | ||||
|             } catch (IOException e) { | ||||
|                 throw new RuntimeException("Unable to close zip. " + key, e); | ||||
|             } | ||||
|         }); | ||||
|         executor.shutdown(); | ||||
|         try { | ||||
|             closeFuture.get(); | ||||
|         } catch (InterruptedException | ExecutionException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|         outputStreams.remove(key); | ||||
|         saveExecutors.remove(key); | ||||
|         if (lineMapWriter != null) { | ||||
|             lineMapWriter.flush(); | ||||
|             lineMapWriter.close(); | ||||
|         } | ||||
|     } | ||||
| 	@Override | ||||
| 	public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { | ||||
| 		this.saveClassEntry(path, archiveName, qualifiedName, entryName, content, null); | ||||
| 	} | ||||
| 
 | ||||
|     //@formatter:off | ||||
|     @Override public void saveFolder(String path) { } | ||||
|     @Override public void copyFile(String source, String path, String entryName) { } | ||||
|     @Override public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { } | ||||
|     @Override public void saveDirEntry(String path, String archiveName, String entryName) { } | ||||
|     @Override public void copyEntry(String source, String path, String archiveName, String entry) { } | ||||
|     //@formatter:on | ||||
| 	@Override | ||||
| 	public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content, int[] mapping) { | ||||
| 		String key = path + "/" + archiveName; | ||||
| 		ExecutorService executor = saveExecutors.get(key); | ||||
| 		executor.submit(() -> { | ||||
| 			ZipOutputStream zos = outputStreams.get(key); | ||||
| 
 | ||||
| 			try { | ||||
| 				zos.putNextEntry(new ZipEntry(entryName)); | ||||
| 
 | ||||
| 				if (content != null) { | ||||
| 					zos.write(content.getBytes(StandardCharsets.UTF_8)); | ||||
| 				} | ||||
| 			} catch (IOException e) { | ||||
| 				DecompilerContext.getLogger().writeMessage("Cannot write entry " + entryName, e); | ||||
| 			} | ||||
| 
 | ||||
| 			if (mapping != null && lineMapWriter != null) { | ||||
| 				int maxLine = 0; | ||||
| 				int maxLineDest = 0; | ||||
| 				StringBuilder builder = new StringBuilder(); | ||||
| 
 | ||||
| 				for (int i = 0; i < mapping.length; i += 2) { | ||||
| 					maxLine = Math.max(maxLine, mapping[i]); | ||||
| 					maxLineDest = Math.max(maxLineDest, mapping[i + 1]); | ||||
| 					builder.append("\t").append(mapping[i]).append("\t").append(mapping[i + 1]).append("\n"); | ||||
| 				} | ||||
| 
 | ||||
| 				lineMapWriter.println(qualifiedName + "\t" + maxLine + "\t" + maxLineDest); | ||||
| 				lineMapWriter.println(builder.toString()); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void closeArchive(String path, String archiveName) { | ||||
| 		String key = path + "/" + archiveName; | ||||
| 		ExecutorService executor = saveExecutors.get(key); | ||||
| 		Future<?> closeFuture = executor.submit(() -> { | ||||
| 			ZipOutputStream zos = outputStreams.get(key); | ||||
| 
 | ||||
| 			try { | ||||
| 				zos.close(); | ||||
| 			} catch (IOException e) { | ||||
| 				throw new RuntimeException("Unable to close zip. " + key, e); | ||||
| 			} | ||||
| 		}); | ||||
| 		executor.shutdown(); | ||||
| 
 | ||||
| 		try { | ||||
| 			closeFuture.get(); | ||||
| 		} catch (InterruptedException | ExecutionException e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 
 | ||||
| 		outputStreams.remove(key); | ||||
| 		saveExecutors.remove(key); | ||||
| 
 | ||||
| 		if (lineMapWriter != null) { | ||||
| 			lineMapWriter.flush(); | ||||
| 			lineMapWriter.close(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void saveFolder(String path) { | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void copyFile(String source, String path, String entryName) { | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void saveDirEntry(String path, String archiveName, String entryName) { | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void copyEntry(String source, String path, String archiveName, String entry) { | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,15 +24,15 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import com.google.common.hash.HashCode; | ||||
| import com.google.common.hash.Hashing; | ||||
| import com.google.common.io.Files; | ||||
| import org.gradle.api.logging.Logger; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| public class Checksum { | ||||
| 	private static final Logger log = Logging.getLogger(Checksum.class); | ||||
| 
 | ||||
|  | @ -40,18 +40,22 @@ public class Checksum { | |||
| 		if (file == null) { | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		try { | ||||
| 			//noinspection deprecation | ||||
| 			HashCode hash = Files.asByteSource(file).hash(Hashing.sha1()); | ||||
| 			StringBuilder builder = new StringBuilder(); | ||||
| 
 | ||||
| 			for (Byte hashBytes : hash.asBytes()) { | ||||
| 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | ||||
| 			} | ||||
| 
 | ||||
| 			log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); | ||||
| 			return builder.toString().equals(checksum); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,13 +24,11 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableList; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class Constants { | ||||
| 
 | ||||
| 	public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker"; | ||||
| 	public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker"; | ||||
| 
 | ||||
|  | @ -41,13 +39,9 @@ public class Constants { | |||
| 
 | ||||
| 	public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath"; | ||||
| 	public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped"; | ||||
| 	public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of( | ||||
| 			new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), | ||||
| 			new RemappedConfigurationEntry("modApi", "api", true, "compile"), | ||||
| 			new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), | ||||
| 			new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""), | ||||
| 			new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "") | ||||
| 	); | ||||
| 	public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), new RemappedConfigurationEntry("modApi", "api", true, "compile"), | ||||
| 																								new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""), | ||||
| 																								new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "")); | ||||
| 
 | ||||
| 	public static final String INCLUDE = "include"; | ||||
| 	public static final String MINECRAFT = "minecraft"; | ||||
|  |  | |||
|  | @ -32,33 +32,36 @@ import java.util.function.Consumer; | |||
|  * Created by covers1624 on 20/12/18. | ||||
|  */ | ||||
| public class ConsumingOutputStream extends OutputStream { | ||||
| 	private final Consumer<String> consumer; | ||||
| 
 | ||||
|     private final Consumer<String> consumer; | ||||
| 	private StringBuilder buffer = new StringBuilder(); | ||||
| 
 | ||||
|     private StringBuilder buffer = new StringBuilder(); | ||||
| 	public ConsumingOutputStream(Consumer<String> consumer) { | ||||
| 		this.consumer = consumer; | ||||
| 	} | ||||
| 
 | ||||
|     public ConsumingOutputStream(Consumer<String> consumer) { | ||||
|         this.consumer = consumer; | ||||
|     } | ||||
| 	@Override | ||||
| 	public void write(int b) throws IOException { | ||||
| 		char ch = (char) (b & 0xFF); | ||||
| 		buffer.append(ch); | ||||
| 
 | ||||
|     @Override | ||||
|     public void write(int b) throws IOException { | ||||
|         char ch = (char) (b & 0xFF); | ||||
|         buffer.append(ch); | ||||
|         if (ch == '\n' || ch == '\r') { | ||||
|             flush(); | ||||
|         } | ||||
|     } | ||||
| 		if (ch == '\n' || ch == '\r') { | ||||
| 			flush(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     @Override | ||||
|     public void flush() throws IOException { | ||||
|         String str = buffer.toString(); | ||||
|         if (str.endsWith("\r") || str.endsWith("\n")) { | ||||
|             str = str.trim(); | ||||
|             if (!str.isEmpty()) { | ||||
|                 consumer.accept(str); | ||||
|             } | ||||
|             buffer = new StringBuilder(); | ||||
|         } | ||||
|     } | ||||
| 	@Override | ||||
| 	public void flush() throws IOException { | ||||
| 		String str = buffer.toString(); | ||||
| 
 | ||||
| 		if (str.endsWith("\r") || str.endsWith("\n")) { | ||||
| 			str = str.trim(); | ||||
| 
 | ||||
| 			if (!str.isEmpty()) { | ||||
| 				consumer.accept(str); | ||||
| 			} | ||||
| 
 | ||||
| 			buffer = new StringBuilder(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,33 +24,8 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableSet; | ||||
| import com.google.common.collect.Iterables; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonObject; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| 
 | ||||
| import org.apache.commons.io.FilenameUtils; | ||||
| import org.gradle.api.InvalidUserDataException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.ResolvedArtifact; | ||||
| import org.gradle.api.artifacts.ResolvedDependency; | ||||
| import org.gradle.api.artifacts.SelfResolvingDependency; | ||||
| import org.gradle.api.artifacts.query.ArtifactResolutionQuery; | ||||
| import org.gradle.api.artifacts.result.ArtifactResult; | ||||
| import org.gradle.api.artifacts.result.ComponentArtifactsResult; | ||||
| import org.gradle.api.artifacts.result.ResolvedArtifactResult; | ||||
| import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier; | ||||
| import org.gradle.jvm.JvmLibrary; | ||||
| import org.gradle.language.base.artifact.SourcesArtifact; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.Collections; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
|  | @ -60,8 +35,21 @@ import java.util.Set; | |||
| import java.util.function.Consumer; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public abstract class DependencyProvider { | ||||
| import com.google.common.collect.Iterables; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.FilenameUtils; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.gradle.api.InvalidUserDataException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.ResolvedDependency; | ||||
| import org.gradle.api.artifacts.SelfResolvingDependency; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| 
 | ||||
| public abstract class DependencyProvider { | ||||
| 	private LoomDependencyManager dependencyManager; | ||||
| 
 | ||||
| 	public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception; | ||||
|  | @ -73,13 +61,14 @@ public abstract class DependencyProvider { | |||
| 	} | ||||
| 
 | ||||
| 	public void addDependency(Object object, Project project, String target) { | ||||
| 		if(object instanceof File){ | ||||
| 		if (object instanceof File) { | ||||
| 			object = project.files(object); | ||||
| 		} | ||||
| 
 | ||||
| 		project.getDependencies().add(target, object); | ||||
| 	} | ||||
| 
 | ||||
| 	public void register(LoomDependencyManager dependencyManager){ | ||||
| 	public void register(LoomDependencyManager dependencyManager) { | ||||
| 		this.dependencyManager = dependencyManager; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -132,14 +121,17 @@ public abstract class DependencyProvider { | |||
| 
 | ||||
| 		public Optional<File> resolveFile() { | ||||
| 			Set<File> files = resolve(); | ||||
| 
 | ||||
| 			if (files.isEmpty()) { | ||||
| 				return Optional.empty(); | ||||
| 			} else if (files.size() > 1) { | ||||
| 				StringBuilder builder = new StringBuilder(this.toString()); | ||||
| 				builder.append(" resolves to more than one file:"); | ||||
| 
 | ||||
| 				for (File f : files) { | ||||
| 					builder.append("\n\t-").append(f.getAbsolutePath()); | ||||
| 				} | ||||
| 
 | ||||
| 				throw new RuntimeException(builder.toString()); | ||||
| 			} else { | ||||
| 				return files.stream().findFirst(); | ||||
|  | @ -151,11 +143,11 @@ public abstract class DependencyProvider { | |||
| 			return getDepString(); | ||||
| 		} | ||||
| 
 | ||||
| 		public String getDepString(){ | ||||
| 		public String getDepString() { | ||||
| 			return dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion(); | ||||
| 		} | ||||
| 
 | ||||
| 		public String getResolvedDepString(){ | ||||
| 		public String getResolvedDepString() { | ||||
| 			return dependency.getGroup() + ":" + dependency.getName() + ":" + getResolvedVersion(); | ||||
| 		} | ||||
| 	} | ||||
|  | @ -178,7 +170,6 @@ public abstract class DependencyProvider { | |||
| 
 | ||||
| 			default: //File collection, try work out the classifiers | ||||
| 				List<File> sortedFiles = files.stream().sorted(Comparator.comparing(File::getName, Comparator.comparingInt(String::length))).collect(Collectors.toList()); | ||||
| 
 | ||||
| 				//First element in sortedFiles is the one with the shortest name, we presume all the others are different classifier types of this | ||||
| 				File shortest = sortedFiles.remove(0); | ||||
| 				String shortestName = FilenameUtils.removeExtension(shortest.getName()); //name.jar -> name | ||||
|  | @ -192,8 +183,8 @@ public abstract class DependencyProvider { | |||
| 
 | ||||
| 				//We appear to be right, therefore this is the normal dependency file we want | ||||
| 				classifierToFile.put("", shortest); | ||||
| 
 | ||||
| 				int start = shortestName.length(); | ||||
| 
 | ||||
| 				for (File file : sortedFiles) { | ||||
| 					//Now we just have to work out what classifier type the other files are, this shouldn't even return an empty string | ||||
| 					String classifier = FilenameUtils.removeExtension(file.getName()).substring(start); | ||||
|  | @ -206,16 +197,21 @@ public abstract class DependencyProvider { | |||
| 			} | ||||
| 
 | ||||
| 			File root = classifierToFile.get(""); //We've built the classifierToFile map, now to try find a name and version for our dependency | ||||
| 
 | ||||
| 			if ("jar".equals(FilenameUtils.getExtension(root.getName())) && ZipUtil.containsEntry(root, "fabric.mod.json")) { | ||||
| 				//It's a Fabric mod, see how much we can extract out | ||||
| 				JsonObject json = new Gson().fromJson(new String(ZipUtil.unpackEntry(root, "fabric.mod.json"), StandardCharsets.UTF_8), JsonObject.class); | ||||
| 				if (json == null || !json.has("id") || !json.has("version")) throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')'); | ||||
| 
 | ||||
| 				if (json.has("name")) {//Go for the name field if it's got one | ||||
| 				if (json == null || !json.has("id") || !json.has("version")) { | ||||
| 					throw new IllegalArgumentException("Invalid Fabric mod jar: " + root + " (malformed json: " + json + ')'); | ||||
| 				} | ||||
| 
 | ||||
| 				if (json.has("name")) { //Go for the name field if it's got one | ||||
| 					name = json.get("name").getAsString(); | ||||
| 				} else { | ||||
| 					name = json.get("id").getAsString(); | ||||
| 				} | ||||
| 
 | ||||
| 				version = json.get("version").getAsString(); | ||||
| 			} else { | ||||
| 				//Not a Fabric mod, just have to make something up | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import java.io.File; | ||||
|  | @ -29,21 +30,18 @@ import java.net.HttpURLConnection; | |||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| import com.google.common.io.Files; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import com.google.common.io.Files; | ||||
| 
 | ||||
| public class DownloadUtil { | ||||
| 	/** | ||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them | ||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them. | ||||
| 	 * | ||||
| 	 * @param from The URL of the file to be downloaded | ||||
| 	 * @param to The destination to be saved to, and compared against if it exists | ||||
| 	 * @param logger The logger to print everything to, typically from {@link Project#getLogger()} | ||||
| 	 * | ||||
| 	 * @throws IOException If an exception occurs during the process | ||||
| 	 */ | ||||
| 	public static void downloadIfChanged(URL from, File to, Logger logger) throws IOException { | ||||
|  | @ -51,24 +49,28 @@ public class DownloadUtil { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them | ||||
| 	 * Download from the given {@link URL} to the given {@link File} so long as there are differences between them. | ||||
| 	 * | ||||
| 	 * @param from The URL of the file to be downloaded | ||||
| 	 * @param to The destination to be saved to, and compared against if it exists | ||||
| 	 * @param logger The logger to print information to, typically from {@link Project#getLogger()} | ||||
| 	 * @param quiet Whether to only print warnings (when <code>true</code>) or everything | ||||
| 	 * | ||||
| 	 * @throws IOException If an exception occurs during the process | ||||
| 	 */ | ||||
| 	public static void downloadIfChanged(URL from, File to, Logger logger, boolean quiet) throws IOException { | ||||
| 		HttpURLConnection connection = (HttpURLConnection) from.openConnection(); | ||||
| 
 | ||||
| 		//If the output already exists we'll use it's last modified time | ||||
| 		if (to.exists()) connection.setIfModifiedSince(to.lastModified()); | ||||
| 		if (to.exists()) { | ||||
| 			connection.setIfModifiedSince(to.lastModified()); | ||||
| 		} | ||||
| 
 | ||||
| 		//Try use the ETag if there's one for the file we're downloading | ||||
| 		String etag = loadETag(to, logger); | ||||
| 		if (etag != null) connection.setRequestProperty("If-None-Match", etag); | ||||
| 
 | ||||
| 		if (etag != null) { | ||||
| 			connection.setRequestProperty("If-None-Match", etag); | ||||
| 		} | ||||
| 
 | ||||
| 		//We want to download gzip compressed stuff | ||||
| 		connection.setRequestProperty("Accept-Encoding", "gzip"); | ||||
|  | @ -80,21 +82,29 @@ public class DownloadUtil { | |||
| 		connection.connect(); | ||||
| 
 | ||||
| 		int code = connection.getResponseCode(); | ||||
| 
 | ||||
| 		if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { | ||||
| 			//Didn't get what we expected | ||||
| 			throw new IOException(connection.getResponseMessage()); | ||||
| 		} | ||||
| 
 | ||||
| 		long modifyTime = connection.getHeaderFieldDate("Last-Modified", -1); | ||||
| 
 | ||||
| 		if (to.exists() && (code == HttpURLConnection.HTTP_NOT_MODIFIED || modifyTime > 0 && to.lastModified() >= modifyTime)) { | ||||
| 			if (!quiet) logger.info("'{}' Not Modified, skipping.", to); | ||||
| 			if (!quiet) { | ||||
| 				logger.info("'{}' Not Modified, skipping.", to); | ||||
| 			} | ||||
| 
 | ||||
| 			return; //What we've got is already fine | ||||
| 		} | ||||
| 
 | ||||
| 		long contentLength = connection.getContentLengthLong(); | ||||
| 		if (!quiet && contentLength >= 0) logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength)); | ||||
| 
 | ||||
| 		try {//Try download to the output | ||||
| 		if (!quiet && contentLength >= 0) { | ||||
| 			logger.info("'{}' Changed, downloading {}", to, toNiceSize(contentLength)); | ||||
| 		} | ||||
| 
 | ||||
| 		try { //Try download to the output | ||||
| 			FileUtils.copyInputStreamToFile(connection.getInputStream(), to); | ||||
| 		} catch (IOException e) { | ||||
| 			to.delete(); //Probably isn't good if it fails to copy/save | ||||
|  | @ -102,23 +112,27 @@ public class DownloadUtil { | |||
| 		} | ||||
| 
 | ||||
| 		//Set the modify time to match the server's (if we know it) | ||||
| 		if (modifyTime > 0) to.setLastModified(modifyTime); | ||||
| 		if (modifyTime > 0) { | ||||
| 			to.setLastModified(modifyTime); | ||||
| 		} | ||||
| 
 | ||||
| 		//Save the ETag (if we know it) | ||||
| 		String eTag = connection.getHeaderField("ETag"); | ||||
| 
 | ||||
| 		if (eTag != null) { | ||||
| 			//Log if we get a weak ETag and we're not on quiet | ||||
| 			if (!quiet && eTag.startsWith("W/")) logger.warn("Weak ETag found."); | ||||
| 			if (!quiet && eTag.startsWith("W/")) { | ||||
| 				logger.warn("Weak ETag found."); | ||||
| 			} | ||||
| 
 | ||||
| 			saveETag(to, eTag, logger); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name | ||||
| 	 * Creates a new file in the same directory as the given file with <code>.etag</code> on the end of the name. | ||||
| 	 * | ||||
| 	 * @param file The file to produce the ETag for | ||||
| 	 * | ||||
| 	 * @return The (uncreated) ETag file for the given file | ||||
| 	 */ | ||||
| 	private static File getETagFile(File file) { | ||||
|  | @ -126,16 +140,18 @@ public class DownloadUtil { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Attempt to load an ETag for the given file, if it exists | ||||
| 	 * Attempt to load an ETag for the given file, if it exists. | ||||
| 	 * | ||||
| 	 * @param to The file to load an ETag for | ||||
| 	 * @param logger The logger to print errors to if it goes wrong | ||||
| 	 * | ||||
| 	 * @return The ETag for the given file, or <code>null</code> if it doesn't exist | ||||
| 	 */ | ||||
| 	private static String loadETag(File to, Logger logger) { | ||||
| 		File eTagFile = getETagFile(to); | ||||
| 		if (!eTagFile.exists()) return null; | ||||
| 
 | ||||
| 		if (!eTagFile.exists()) { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		try { | ||||
| 			return Files.asCharSource(eTagFile, StandardCharsets.UTF_8).read(); | ||||
|  | @ -146,7 +162,7 @@ public class DownloadUtil { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Saves the given ETag for the given file, replacing it if it already exists | ||||
| 	 * Saves the given ETag for the given file, replacing it if it already exists. | ||||
| 	 * | ||||
| 	 * @param to The file to save the ETag for | ||||
| 	 * @param eTag The ETag to be saved | ||||
|  | @ -154,8 +170,12 @@ public class DownloadUtil { | |||
| 	 */ | ||||
| 	private static void saveETag(File to, String eTag, Logger logger) { | ||||
| 		File eTagFile = getETagFile(to); | ||||
| 
 | ||||
| 		try { | ||||
| 			if (!eTagFile.exists()) eTagFile.createNewFile(); | ||||
| 			if (!eTagFile.exists()) { | ||||
| 				eTagFile.createNewFile(); | ||||
| 			} | ||||
| 
 | ||||
| 			Files.asCharSink(eTagFile, StandardCharsets.UTF_8).write(eTag); | ||||
| 		} catch (IOException e) { | ||||
| 			logger.warn("Error saving ETag file '{}'.", eTagFile, e); | ||||
|  | @ -163,10 +183,9 @@ public class DownloadUtil { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Format the given number of bytes as a more human readable string | ||||
| 	 * Format the given number of bytes as a more human readable string. | ||||
| 	 * | ||||
| 	 * @param bytes The number of bytes | ||||
| 	 * | ||||
| 	 * @return The given number of bytes formatted to kilobytes, megabytes or gigabytes if appropriate | ||||
| 	 */ | ||||
| 	private static String toNiceSize(long bytes) { | ||||
|  | @ -192,6 +211,7 @@ public class DownloadUtil { | |||
| 		} | ||||
| 
 | ||||
| 		File etagFile = getETagFile(file); | ||||
| 
 | ||||
| 		if (etagFile.exists()) { | ||||
| 			etagFile.delete(); | ||||
| 		} | ||||
|  |  | |||
|  | @ -24,23 +24,23 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.file.RegularFileProperty; | ||||
| import org.gradle.api.model.ObjectFactory; | ||||
| 
 | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| 
 | ||||
| //This is used to bridge the gap over large gradle api changes. | ||||
| public class GradleSupport { | ||||
| 
 | ||||
| 	public static RegularFileProperty getfileProperty(Project project){ | ||||
| 	public static RegularFileProperty getfileProperty(Project project) { | ||||
| 		try { | ||||
| 			//First try the new method, if that fails fall back. | ||||
| 			return getfilePropertyModern(project); | ||||
| 		} catch (Exception e){ | ||||
| 		} catch (Exception e) { | ||||
| 			//Nope | ||||
| 		} | ||||
| 
 | ||||
| 		return getfilePropertyLegacy(project); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -51,7 +51,7 @@ public class GradleSupport { | |||
| 		return (RegularFileProperty) method.invoke(objectFactory); | ||||
| 	} | ||||
| 
 | ||||
| 	private static RegularFileProperty getfilePropertyLegacy(Project project){ | ||||
| 	private static RegularFileProperty getfilePropertyLegacy(Project project) { | ||||
| 		return project.getLayout().fileProperty(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,17 +24,15 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import groovy.util.Node; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| public final class GroovyXmlUtil { | ||||
| 	private GroovyXmlUtil() { | ||||
| import groovy.util.Node; | ||||
| 
 | ||||
| 	} | ||||
| public final class GroovyXmlUtil { | ||||
| 	private GroovyXmlUtil() { } | ||||
| 
 | ||||
| 	public static Node getOrCreateNode(Node parent, String name) { | ||||
| 		for (Object object : parent.children()) { | ||||
|  |  | |||
|  | @ -24,138 +24,160 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| import org.gradle.api.logging.Logger; | ||||
| import org.objectweb.asm.*; | ||||
| import static java.text.MessageFormat.format; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.nio.file.*; | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.nio.file.FileVisitResult; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.SimpleFileVisitor; | ||||
| import java.nio.file.StandardCopyOption; | ||||
| import java.nio.file.attribute.BasicFileAttributes; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import static java.text.MessageFormat.format; | ||||
| import org.objectweb.asm.ClassReader; | ||||
| import org.objectweb.asm.ClassVisitor; | ||||
| import org.objectweb.asm.ClassWriter; | ||||
| import org.objectweb.asm.Label; | ||||
| import org.objectweb.asm.MethodVisitor; | ||||
| import org.objectweb.asm.Opcodes; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.progress.ProgressLogger; | ||||
| 
 | ||||
| /** | ||||
|  * TODO, Move to stitch. | ||||
|  * Created by covers1624 on 18/02/19. | ||||
|  */ | ||||
| public class LineNumberRemapper { | ||||
| 	private final Map<String, RClass> lineMap = new HashMap<>(); | ||||
| 
 | ||||
|     private final Map<String, RClass> lineMap = new HashMap<>(); | ||||
| 	public void readMappings(File lineMappings) { | ||||
| 		try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { | ||||
| 			RClass clazz = null; | ||||
| 			String line = null; | ||||
| 			int i = 0; | ||||
| 
 | ||||
|     public void readMappings(File lineMappings) { | ||||
|         try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { | ||||
|             RClass clazz = null; | ||||
|             String line = null; | ||||
|             int i = 0; | ||||
|             try { | ||||
|                 while ((line = reader.readLine()) != null) { | ||||
|                     if (line.isEmpty()) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     String[] segs = line.trim().split("\t"); | ||||
|                     if (line.charAt(0) != '\t') { | ||||
|                         clazz = lineMap.computeIfAbsent(segs[0], RClass::new); | ||||
|                         clazz.maxLine = Integer.parseInt(segs[1]); | ||||
|                         clazz.maxLineDest = Integer.parseInt(segs[2]); | ||||
|                     } else { | ||||
|                         clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1])); | ||||
|                     } | ||||
|                     i++; | ||||
|                 } | ||||
|             } catch (Exception e) { | ||||
|                 throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e); | ||||
|             } | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException("Exception reading LineMappings file.", e); | ||||
|         } | ||||
|     } | ||||
| 			try { | ||||
| 				while ((line = reader.readLine()) != null) { | ||||
| 					if (line.isEmpty()) { | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
|     public void process(ProgressLogger logger, Path input, Path output) throws IOException { | ||||
|         Files.walkFileTree(input, new SimpleFileVisitor<Path>() { | ||||
|             @Override | ||||
|             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { | ||||
|                 String rel = input.relativize(file).toString(); | ||||
|                 Path dst = output.resolve(rel); | ||||
|                 Path parent = dst.getParent(); | ||||
|                 if (parent != null) { | ||||
|                     Files.createDirectories(parent); | ||||
|                 } | ||||
|                 String fName = file.getFileName().toString(); | ||||
|                 if (fName.endsWith(".class")) { | ||||
|                     if (Files.exists(dst)) { | ||||
|                         Files.delete(dst); | ||||
|                     } | ||||
|                     String idx = rel.substring(0, rel.length() - 6); | ||||
|                     if (logger != null) { | ||||
|                         logger.progress("Remapping " + idx); | ||||
|                     } | ||||
| 					String[] segs = line.trim().split("\t"); | ||||
| 
 | ||||
|                     int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped. | ||||
|                     if (dollarPos >= 0) { | ||||
|                         idx = idx.substring(0, dollarPos); | ||||
|                     } | ||||
|                     if (lineMap.containsKey(idx)) { | ||||
|                         try (InputStream is = Files.newInputStream(file)) { | ||||
|                             ClassReader reader = new ClassReader(is); | ||||
|                             ClassWriter writer = new ClassWriter(0); | ||||
| 					if (line.charAt(0) != '\t') { | ||||
| 						clazz = lineMap.computeIfAbsent(segs[0], RClass::new); | ||||
| 						clazz.maxLine = Integer.parseInt(segs[1]); | ||||
| 						clazz.maxLineDest = Integer.parseInt(segs[2]); | ||||
| 					} else { | ||||
| 						clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1])); | ||||
| 					} | ||||
| 
 | ||||
|                             reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0); | ||||
|                             Files.write(dst, writer.toByteArray()); | ||||
|                         } | ||||
|                     } | ||||
| 					i++; | ||||
| 				} | ||||
| 			} catch (Exception e) { | ||||
| 				throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e); | ||||
| 			} | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Exception reading LineMappings file.", e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|                 } else { | ||||
|                     Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); | ||||
|                 } | ||||
| 	public void process(ProgressLogger logger, Path input, Path output) throws IOException { | ||||
| 		Files.walkFileTree(input, new SimpleFileVisitor<Path>() { | ||||
| 			@Override | ||||
| 			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { | ||||
| 				String rel = input.relativize(file).toString(); | ||||
| 				Path dst = output.resolve(rel); | ||||
| 				Path parent = dst.getParent(); | ||||
| 
 | ||||
|                 return FileVisitResult.CONTINUE; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 				if (parent != null) { | ||||
| 					Files.createDirectories(parent); | ||||
| 				} | ||||
| 
 | ||||
|     private static class LineNumberVisitor extends ClassVisitor { | ||||
| 				String fName = file.getFileName().toString(); | ||||
| 
 | ||||
|         private final RClass rClass; | ||||
| 				if (fName.endsWith(".class")) { | ||||
| 					if (Files.exists(dst)) { | ||||
| 						Files.delete(dst); | ||||
| 					} | ||||
| 
 | ||||
|         public LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { | ||||
|             super(api, classVisitor); | ||||
|             this.rClass = rClass; | ||||
|         } | ||||
| 					String idx = rel.substring(0, rel.length() - 6); | ||||
| 
 | ||||
|         @Override | ||||
|         public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { | ||||
|             return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { | ||||
|                 @Override | ||||
|                 public void visitLineNumber(int line, Label start) { | ||||
|                     int tLine = line; | ||||
|                     if (tLine <= 0) { | ||||
|                         super.visitLineNumber(line, start); | ||||
|                     } else if (tLine >= rClass.maxLine) { | ||||
|                         super.visitLineNumber(rClass.maxLineDest, start); | ||||
|                     } else { | ||||
|                         Integer matchedLine = null; | ||||
|                         while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) { | ||||
|                             tLine++; | ||||
|                         } | ||||
|                         super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start); | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| 					if (logger != null) { | ||||
| 						logger.progress("Remapping " + idx); | ||||
| 					} | ||||
| 
 | ||||
|     private static class RClass { | ||||
| 					int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped. | ||||
| 
 | ||||
|         private final String name; | ||||
|         private int maxLine; | ||||
|         private int maxLineDest; | ||||
|         private Map<Integer, Integer> lineMap = new HashMap<>(); | ||||
| 					if (dollarPos >= 0) { | ||||
| 						idx = idx.substring(0, dollarPos); | ||||
| 					} | ||||
| 
 | ||||
|         private RClass(String name) { | ||||
|             this.name = name; | ||||
|         } | ||||
|     } | ||||
| 					if (lineMap.containsKey(idx)) { | ||||
| 						try (InputStream is = Files.newInputStream(file)) { | ||||
| 							ClassReader reader = new ClassReader(is); | ||||
| 							ClassWriter writer = new ClassWriter(0); | ||||
| 
 | ||||
| 							reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0); | ||||
| 							Files.write(dst, writer.toByteArray()); | ||||
| 						} | ||||
| 					} | ||||
| 				} else { | ||||
| 					Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); | ||||
| 				} | ||||
| 
 | ||||
| 				return FileVisitResult.CONTINUE; | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	private static class LineNumberVisitor extends ClassVisitor { | ||||
| 		private final RClass rClass; | ||||
| 
 | ||||
| 		LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { | ||||
| 			super(api, classVisitor); | ||||
| 			this.rClass = rClass; | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { | ||||
| 			return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { | ||||
| 				@Override | ||||
| 				public void visitLineNumber(int line, Label start) { | ||||
| 					int tLine = line; | ||||
| 
 | ||||
| 					if (tLine <= 0) { | ||||
| 						super.visitLineNumber(line, start); | ||||
| 					} else if (tLine >= rClass.maxLine) { | ||||
| 						super.visitLineNumber(rClass.maxLineDest, start); | ||||
| 					} else { | ||||
| 						Integer matchedLine = null; | ||||
| 
 | ||||
| 						while (tLine <= rClass.maxLine && ((matchedLine = rClass.lineMap.get(tLine)) == null)) { | ||||
| 							tLine++; | ||||
| 						} | ||||
| 
 | ||||
| 						super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start); | ||||
| 					} | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static class RClass { | ||||
| 		private final String name; | ||||
| 		private int maxLine; | ||||
| 		private int maxLineDest; | ||||
| 		private Map<Integer, Integer> lineMap = new HashMap<>(); | ||||
| 
 | ||||
| 		private RClass(String name) { | ||||
| 			this.name = name; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,19 +24,24 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.gson.JsonObject; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.util.DependencyProvider.DependencyInfo; | ||||
| import java.io.File; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import com.google.gson.JsonObject; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.ExternalModuleDependency; | ||||
| import org.gradle.api.artifacts.repositories.MavenArtifactRepository; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.*; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.util.DependencyProvider.DependencyInfo; | ||||
| 
 | ||||
| public class LoomDependencyManager { | ||||
| 	private static class ProviderList { | ||||
|  | @ -50,27 +55,30 @@ public class LoomDependencyManager { | |||
| 
 | ||||
| 	private List<DependencyProvider> dependencyProviderList = new ArrayList<>(); | ||||
| 
 | ||||
| 	public void addProvider(DependencyProvider provider){ | ||||
| 		if(dependencyProviderList.contains(provider)){ | ||||
| 	public void addProvider(DependencyProvider provider) { | ||||
| 		if (dependencyProviderList.contains(provider)) { | ||||
| 			throw new RuntimeException("Provider is already registered"); | ||||
| 		} | ||||
| 		if(getProvider(provider.getClass()) != null){ | ||||
| 
 | ||||
| 		if (getProvider(provider.getClass()) != null) { | ||||
| 			throw new RuntimeException("Provider of this type is already registered"); | ||||
| 		} | ||||
| 
 | ||||
| 		provider.register(this); | ||||
| 		dependencyProviderList.add(provider); | ||||
| 	} | ||||
| 
 | ||||
| 	public <T> T getProvider(Class<T> clazz){ | ||||
| 		for(DependencyProvider provider : dependencyProviderList){ | ||||
| 			if(provider.getClass() == clazz){ | ||||
| 	public <T> T getProvider(Class<T> clazz) { | ||||
| 		for (DependencyProvider provider : dependencyProviderList) { | ||||
| 			if (provider.getClass() == clazz) { | ||||
| 				return (T) provider; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	public void handleDependencies(Project project){ | ||||
| 	public void handleDependencies(Project project) { | ||||
| 		List<Runnable> afterTasks = new ArrayList<>(); | ||||
| 
 | ||||
| 		MappingsProvider mappingsProvider = null; | ||||
|  | @ -80,7 +88,7 @@ public class LoomDependencyManager { | |||
| 		Map<String, ProviderList> providerListMap = new HashMap<>(); | ||||
| 		List<ProviderList> targetProviders = new ArrayList<>(); | ||||
| 
 | ||||
| 		for(DependencyProvider provider : dependencyProviderList){ | ||||
| 		for (DependencyProvider provider : dependencyProviderList) { | ||||
| 			providerListMap.computeIfAbsent(provider.getTargetConfig(), (k) -> { | ||||
| 				ProviderList list = new ProviderList(k); | ||||
| 				targetProviders.add(list); | ||||
|  | @ -101,6 +109,7 @@ public class LoomDependencyManager { | |||
| 			configuration.getDependencies().forEach(dependency -> { | ||||
| 				for (DependencyProvider provider : list.providers) { | ||||
| 					DependencyProvider.DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | ||||
| 
 | ||||
| 					try { | ||||
| 						provider.provide(info, project, extension, afterTasks::add); | ||||
| 					} catch (Exception e) { | ||||
|  | @ -114,13 +123,7 @@ public class LoomDependencyManager { | |||
| 			String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion; | ||||
| 
 | ||||
| 			for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | ||||
| 				ModCompileRemapper.remapDependencies( | ||||
| 						project, mappingsKey, extension, | ||||
| 						project.getConfigurations().getByName(entry.getSourceConfiguration()), | ||||
| 						project.getConfigurations().getByName(entry.getRemappedConfiguration()), | ||||
| 						project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), | ||||
| 						afterTasks::add | ||||
| 				); | ||||
| 				ModCompileRemapper.remapDependencies(project, mappingsKey, extension, project.getConfigurations().getByName(entry.getSourceConfiguration()), project.getConfigurations().getByName(entry.getRemappedConfiguration()), project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), afterTasks::add); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -133,9 +136,11 @@ public class LoomDependencyManager { | |||
| 
 | ||||
| 			for (Dependency dependency : configuration.getDependencies()) { | ||||
| 				DependencyInfo info = DependencyInfo.create(project, dependency, configuration); | ||||
| 
 | ||||
| 				for (File input : info.resolve()) { | ||||
| 					if (seenFiles.add(input)) { | ||||
| 						ModProcessor.readInstallerJson(input, project); | ||||
| 
 | ||||
| 						if (extension.getInstallerJson() != null) { | ||||
| 							project.getLogger().info("Found installer JSON in " + info); | ||||
| 							break; //Found it, probably don't need to look any further | ||||
|  | @ -156,7 +161,7 @@ public class LoomDependencyManager { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static void handleInstallerJson(JsonObject jsonObject, Project project){ | ||||
| 	private static void handleInstallerJson(JsonObject jsonObject, Project project) { | ||||
| 		JsonObject libraries = jsonObject.get("libraries").getAsJsonObject(); | ||||
| 		Configuration mcDepsConfig = project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES); | ||||
| 		Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor"); | ||||
|  | @ -171,16 +176,15 @@ public class LoomDependencyManager { | |||
| 
 | ||||
| 			project.getLogger().debug("Loom adding " + name + " from installer JSON"); | ||||
| 
 | ||||
| 			if(jsonElement.getAsJsonObject().has("url")){ | ||||
| 			if (jsonElement.getAsJsonObject().has("url")) { | ||||
| 				String url = jsonElement.getAsJsonObject().get("url").getAsString(); | ||||
| 				long count = project.getRepositories().stream() | ||||
| 						.filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository) | ||||
| 				long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository) | ||||
| 						.map(artifactRepository -> (MavenArtifactRepository) artifactRepository) | ||||
| 						.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count(); | ||||
| 				if(count == 0){ | ||||
| 
 | ||||
| 				if (count == 0) { | ||||
| 					project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString())); | ||||
| 				} | ||||
| 
 | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
|  | @ -24,32 +24,28 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| import net.fabricmc.tinyremapper.TinyUtils; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Arrays; | ||||
| 
 | ||||
| public class MapJarsTiny { | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| 
 | ||||
| public class MapJarsTiny { | ||||
| 	public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, Project project) throws IOException { | ||||
| 		String fromM = "official"; | ||||
| 
 | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		Path[] classpath = mapProvider.getMapperPaths().stream() | ||||
| 				.map(File::toPath) | ||||
| 				.toArray(Path[]::new); | ||||
| 		Path[] classpath = mapProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new); | ||||
| 
 | ||||
| 		Path input = jarProvider.getMergedJar().toPath(); | ||||
| 		Path outputMapped = mapProvider.getMappedJar().toPath(); | ||||
|  | @ -60,11 +56,7 @@ public class MapJarsTiny { | |||
| 
 | ||||
| 			project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); | ||||
| 
 | ||||
| 			TinyRemapper remapper = TinyRemapper.newRemapper() | ||||
| 					.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)) | ||||
| 					.renameInvalidLocals(true) | ||||
| 					.rebuildSourceFilenames(true) | ||||
| 					.build(); | ||||
| 			TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).renameInvalidLocals(true).rebuildSourceFilenames(true).build(); | ||||
| 
 | ||||
| 			try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { | ||||
| 				outputConsumer.addNonClassFiles(input); | ||||
|  |  | |||
|  | @ -24,15 +24,13 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftLibraryProvider; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | ||||
| 
 | ||||
| public class MinecraftVersionInfo { | ||||
| 	public List<Library> libraries; | ||||
| 	public Map<String, Downloads> downloads; | ||||
|  | @ -93,14 +91,16 @@ public class MinecraftVersionInfo { | |||
| 				return ""; | ||||
| 			} else { | ||||
| 				JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())); | ||||
| 				if(element == null){ | ||||
| 
 | ||||
| 				if (element == null) { | ||||
| 					return ""; | ||||
| 				} | ||||
| 
 | ||||
| 				return "-" + element.getAsString().replace("\"", ""); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public boolean isNative(){ | ||||
| 		public boolean isNative() { | ||||
| 			return getClassifier().contains("natives"); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -110,6 +110,7 @@ public class MinecraftVersionInfo { | |||
| 			} | ||||
| 
 | ||||
| 			boolean success = false; | ||||
| 
 | ||||
| 			for (Rule rule : this.rules) { | ||||
| 				if (rule.os != null && rule.os.name != null) { | ||||
| 					if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { | ||||
|  | @ -119,6 +120,7 @@ public class MinecraftVersionInfo { | |||
| 					success = rule.action.equalsIgnoreCase("allow"); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			return success; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -126,9 +128,11 @@ public class MinecraftVersionInfo { | |||
| 			if (artifact == null) { | ||||
| 				artifact = new Artifact(name); | ||||
| 			} | ||||
| 			if(natives != null){ | ||||
| 
 | ||||
| 			if (natives != null) { | ||||
| 				JsonElement jsonElement = natives.get(OperatingSystem.getOS()); | ||||
| 				if(jsonElement != null){ | ||||
| 
 | ||||
| 				if (jsonElement != null) { | ||||
| 					return artifact.getArtifact(jsonElement.getAsString()); | ||||
| 				} | ||||
| 			} | ||||
|  | @ -139,15 +143,17 @@ public class MinecraftVersionInfo { | |||
| 		private class Artifact { | ||||
| 			private final String domain, name, version, classifier, ext; | ||||
| 
 | ||||
| 			public Artifact(String name) { | ||||
| 			Artifact(String name) { | ||||
| 				String[] splitedArtifact = name.split(":"); | ||||
| 				int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); | ||||
| 
 | ||||
| 				if (idx != -1) { | ||||
| 					ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); | ||||
| 					splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); | ||||
| 				} else { | ||||
| 					ext = "jar"; | ||||
| 				} | ||||
| 
 | ||||
| 				this.domain = splitedArtifact[0]; | ||||
| 				this.name = splitedArtifact[1]; | ||||
| 				this.version = splitedArtifact[2]; | ||||
|  | @ -156,15 +162,19 @@ public class MinecraftVersionInfo { | |||
| 
 | ||||
| 			public String getArtifact(String classifier) { | ||||
| 				String ret = domain + ":" + name + ":" + version; | ||||
| 
 | ||||
| 				if (classifier != null && classifier.indexOf('$') > -1) { | ||||
| 					classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); | ||||
| 				} | ||||
| 
 | ||||
| 				if (classifier != null) { | ||||
| 					ret += ":" + classifier; | ||||
| 				} | ||||
| 
 | ||||
| 				if (!"jar".equals(ext)) { | ||||
| 					ret += "@" + ext; | ||||
| 				} | ||||
| 
 | ||||
| 				return ret; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,15 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.gson.JsonObject; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| import org.objectweb.asm.commons.Remapper; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
|  | @ -41,86 +32,91 @@ import java.util.HashSet; | |||
| import java.util.Set; | ||||
| import java.util.zip.ZipEntry; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| 
 | ||||
| public final class MixinRefmapHelper { | ||||
|     private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | ||||
| 	private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | ||||
| 
 | ||||
|     private MixinRefmapHelper() { | ||||
| 	private MixinRefmapHelper() { } | ||||
| 
 | ||||
|     } | ||||
| 	public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) { | ||||
| 		File output = outputPath.toFile(); | ||||
| 		Set<String> mixinFilenames = findMixins(output, true); | ||||
| 
 | ||||
|     public static boolean addRefmapName(String filename, String mixinVersion, Path outputPath) { | ||||
|         File output = outputPath.toFile(); | ||||
|         Set<String> mixinFilenames = findMixins(output, true); | ||||
| 		if (mixinFilenames.size() > 0) { | ||||
| 			return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { | ||||
| 				@Override | ||||
| 				protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||
| 					JsonObject json = GSON.fromJson(input, JsonObject.class); | ||||
| 
 | ||||
|         if (mixinFilenames.size() > 0) { | ||||
|             return ZipUtil.transformEntries( | ||||
|                     output, | ||||
|                     mixinFilenames.stream() | ||||
|                             .map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { | ||||
|                                 @Override | ||||
|                                 protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||
|                                     JsonObject json = GSON.fromJson(input, JsonObject.class); | ||||
|                                     if (!json.has("refmap")) { | ||||
|                                         json.addProperty("refmap", filename); | ||||
|                                     } | ||||
|                                     if (!json.has("minVersion") && mixinVersion != null) { | ||||
|                                         json.addProperty("minVersion", mixinVersion); | ||||
|                                     } | ||||
|                                     return GSON.toJson(json); | ||||
|                                 } | ||||
|                             })).toArray(ZipEntryTransformerEntry[]::new) | ||||
|             ); | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 					if (!json.has("refmap")) { | ||||
| 						json.addProperty("refmap", filename); | ||||
| 					} | ||||
| 
 | ||||
|     private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { | ||||
|         // first, identify all of the mixin files | ||||
|         Set<String> mixinFilename = new HashSet<>(); | ||||
|         // TODO: this is a lovely hack | ||||
|         ZipUtil.iterate(output, (stream, entry) -> { | ||||
|             if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||
|                 // JSON file in root directory | ||||
|                 try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||
|                     JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||
| 					if (!json.has("minVersion") && mixinVersion != null) { | ||||
| 						json.addProperty("minVersion", mixinVersion); | ||||
| 					} | ||||
| 
 | ||||
|                     if (json != null) { | ||||
|                         boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); | ||||
|                         boolean hasClient = json.has("client") && json.get("client").isJsonArray(); | ||||
|                         boolean hasServer = json.has("server") && json.get("server").isJsonArray(); | ||||
| 					return GSON.toJson(json); | ||||
| 				} | ||||
| 			})).toArray(ZipEntryTransformerEntry[]::new)); | ||||
| 		} else { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|                         if (json.has("package") && (hasMixins || hasClient || hasServer)) { | ||||
|                             if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { | ||||
|                                 mixinFilename.add(entry.getName()); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } catch (Exception e) { | ||||
|                     // ... | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         return mixinFilename; | ||||
|     } | ||||
| 	private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { | ||||
| 		// first, identify all of the mixin files | ||||
| 		Set<String> mixinFilename = new HashSet<>(); | ||||
| 		// TODO: this is a lovely hack | ||||
| 		ZipUtil.iterate(output, (stream, entry) -> { | ||||
| 			if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||
| 				// JSON file in root directory | ||||
| 				try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||
| 					JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||
| 
 | ||||
|     private static Set<String> findRefmaps(File output) { | ||||
|         // first, identify all of the mixin refmaps | ||||
|         Set<String> mixinRefmapFilenames = new HashSet<>(); | ||||
|         // TODO: this is also a lovely hack | ||||
|         ZipUtil.iterate(output, (stream, entry) -> { | ||||
|             if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||
|                 // JSON file in root directory | ||||
|                 try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||
|                     JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||
|                     if (json != null && json.has("refmap")) { | ||||
|                         mixinRefmapFilenames.add(json.get("refmap").getAsString()); | ||||
|                     } | ||||
|                 } catch (Exception e) { | ||||
|                     // ... | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         return mixinRefmapFilenames; | ||||
|     } | ||||
| 					if (json != null) { | ||||
| 						boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); | ||||
| 						boolean hasClient = json.has("client") && json.get("client").isJsonArray(); | ||||
| 						boolean hasServer = json.has("server") && json.get("server").isJsonArray(); | ||||
| 
 | ||||
| 						if (json.has("package") && (hasMixins || hasClient || hasServer)) { | ||||
| 							if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { | ||||
| 								mixinFilename.add(entry.getName()); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} catch (Exception e) { | ||||
| 					// ... | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		return mixinFilename; | ||||
| 	} | ||||
| 
 | ||||
| 	private static Set<String> findRefmaps(File output) { | ||||
| 		// first, identify all of the mixin refmaps | ||||
| 		Set<String> mixinRefmapFilenames = new HashSet<>(); | ||||
| 		// TODO: this is also a lovely hack | ||||
| 		ZipUtil.iterate(output, (stream, entry) -> { | ||||
| 			if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||
| 				// JSON file in root directory | ||||
| 				try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||
| 					JsonObject json = GSON.fromJson(inputStreamReader, JsonObject.class); | ||||
| 
 | ||||
| 					if (json != null && json.has("refmap")) { | ||||
| 						mixinRefmapFilenames.add(json.get("refmap").getAsString()); | ||||
| 					} | ||||
| 				} catch (Exception e) { | ||||
| 					// ... | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		return mixinRefmapFilenames; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,7 +24,11 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
|  | @ -40,10 +44,7 @@ import org.gradle.api.logging.Logger; | |||
| import org.gradle.jvm.JvmLibrary; | ||||
| import org.gradle.language.base.artifact.SourcesArtifact; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| import java.util.function.Consumer; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| 
 | ||||
| public class ModCompileRemapper { | ||||
| 	public static void remapDependencies(Project project, String mappingsPrefix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) { | ||||
|  | @ -93,7 +94,7 @@ public class ModCompileRemapper { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json | ||||
| 	 * Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json. | ||||
| 	 */ | ||||
| 	private static boolean isFabricMod(Project project, Logger logger, ResolvedArtifact artifact, String notation) { | ||||
| 		File input = artifact.getFile(); | ||||
|  | @ -112,15 +113,18 @@ public class ModCompileRemapper { | |||
| 		project.getLogger().info(":providing " + notation); | ||||
| 		DependencyHandler dependencies = project.getDependencies(); | ||||
| 		Dependency dep = dependencies.module(notation); | ||||
| 
 | ||||
| 		if (dep instanceof ModuleDependency) { | ||||
| 			((ModuleDependency) dep).setTransitive(false); | ||||
| 		} | ||||
| 
 | ||||
| 		dependencies.add(regularCompile.getName(), dep); | ||||
| 	} | ||||
| 
 | ||||
| 	private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) { | ||||
| 		File input = artifact.getFile(); | ||||
| 		File output = new File(modStore, remappedFilename + ".jar"); | ||||
| 
 | ||||
| 		if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) { | ||||
| 			//If the output doesn't exist, or appears to be outdated compared to the input we'll remap it | ||||
| 			try { | ||||
|  | @ -129,7 +133,7 @@ public class ModCompileRemapper { | |||
| 				throw new RuntimeException("Failed to remap mod", e); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!output.exists()){ | ||||
| 			if (!output.exists()) { | ||||
| 				throw new RuntimeException("Failed to remap mod"); | ||||
| 			} | ||||
| 
 | ||||
|  | @ -142,10 +146,10 @@ public class ModCompileRemapper { | |||
| 	} | ||||
| 
 | ||||
| 	private static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) { | ||||
| 		@SuppressWarnings ("unchecked") | ||||
| 		ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()// | ||||
| 		@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()// | ||||
| 				.forComponents(artifact.getId().getComponentIdentifier())// | ||||
| 				.withArtifacts(JvmLibrary.class, SourcesArtifact.class); | ||||
| 
 | ||||
| 		for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { | ||||
| 			for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { | ||||
| 				if (srcArtifact instanceof ResolvedArtifactResult) { | ||||
|  | @ -153,6 +157,7 @@ public class ModCompileRemapper { | |||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,23 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonObject; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.internal.impldep.aQute.lib.strings.Strings; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.commons.FileUtils; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
|  | @ -54,18 +37,39 @@ import java.util.jar.JarEntry; | |||
| import java.util.jar.JarFile; | ||||
| import java.util.zip.ZipEntry; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.commons.FileUtils; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.internal.impldep.aQute.lib.strings.Strings; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftMappedProvider; | ||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
| import net.fabricmc.tinyremapper.TinyRemapper; | ||||
| 
 | ||||
| public class ModProcessor { | ||||
| 	private static final Gson GSON = new Gson(); | ||||
| 
 | ||||
| 	public static void processMod(File input, File output, Project project, Configuration config) throws IOException { | ||||
| 		if(output.exists()){ | ||||
| 		if (output.exists()) { | ||||
| 			output.delete(); | ||||
| 		} | ||||
| 
 | ||||
| 		remapJar(input, output, project); | ||||
| 
 | ||||
| 		//Enable this if you want your nested jars to be extracted, this will extract **all** jars | ||||
| 		if(project.getExtensions().getByType(LoomGradleExtension.class).extractJars){ | ||||
| 		if (project.getExtensions().getByType(LoomGradleExtension.class).extractJars) { | ||||
| 			handleNestedJars(input, project, config); | ||||
| 		} | ||||
| 
 | ||||
| 		//Always strip the nested jars | ||||
| 		stripNestedJars(output); | ||||
| 	} | ||||
|  | @ -77,15 +81,20 @@ public class ModProcessor { | |||
| 	private static void handleNestedJars(File input, Project project, Configuration config) throws IOException { | ||||
| 		JarFile jarFile = new JarFile(input); | ||||
| 		JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json"); | ||||
| 		if(modJsonEntry == null){ | ||||
| 
 | ||||
| 		if (modJsonEntry == null) { | ||||
| 			return; | ||||
| 		} | ||||
| 		try(InputStream inputStream = jarFile.getInputStream(modJsonEntry)){ | ||||
| 
 | ||||
| 		try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) { | ||||
| 			JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class); | ||||
| 			if(json == null || !json.has("jars")){ | ||||
| 
 | ||||
| 			if (json == null || !json.has("jars")) { | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			JsonArray jsonArray = json.getAsJsonArray("jars"); | ||||
| 
 | ||||
| 			for (int i = 0; i < jsonArray.size(); i++) { | ||||
| 				JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); | ||||
| 				String fileName = jsonObject.get("file").getAsString(); | ||||
|  | @ -99,19 +108,22 @@ public class ModProcessor { | |||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 
 | ||||
| 		JarEntry entry = parentJar.getJarEntry(fileName); | ||||
| 		if(entry == null){ | ||||
| 
 | ||||
| 		if (entry == null) { | ||||
| 			throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName())); | ||||
| 		} | ||||
| 
 | ||||
| 		File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | ||||
| 		try(InputStream jarStream = parentJar.getInputStream(entry)) { | ||||
| 
 | ||||
| 		try (InputStream jarStream = parentJar.getInputStream(entry)) { | ||||
| 			FileUtils.copy(jarStream, nestedFile); | ||||
| 		} | ||||
| 
 | ||||
| 		File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/"))); | ||||
| 
 | ||||
| 		processMod(nestedFile, remappedFile, project, config); | ||||
| 
 | ||||
| 		if(!remappedFile.exists()){ | ||||
| 		if (!remappedFile.exists()) { | ||||
| 			throw new RuntimeException("Failed to find processed nested jar"); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -119,7 +131,7 @@ public class ModProcessor { | |||
| 		project.getDependencies().add(config.getName(), project.files(remappedFile)); | ||||
| 	} | ||||
| 
 | ||||
| 	private static void stripNestedJars(File file){ | ||||
| 	private static void stripNestedJars(File file) { | ||||
| 		//Strip out all contained jar info as we dont want loader to try and load the jars contained in dev. | ||||
| 		ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { | ||||
| 			@Override | ||||
|  | @ -143,29 +155,22 @@ public class ModProcessor { | |||
| 		Path mappings = mappingsFile.toPath(); | ||||
| 		Path inputPath = input.getAbsoluteFile().toPath(); | ||||
| 		Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath(); | ||||
| 		Path[] mcDeps = mappedProvider.getMapperPaths().stream() | ||||
| 			.map(File::toPath) | ||||
| 			.toArray(Path[]::new); | ||||
| 		Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new); | ||||
| 		Set<Path> modCompiles = new HashSet<>(); | ||||
| 		for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | ||||
| 			project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream() | ||||
| 					.filter((f) -> !f.equals(input)) | ||||
| 					.map(p -> { | ||||
| 						if (p.equals(input)) { | ||||
| 							return inputPath; | ||||
| 						} else { | ||||
| 							return p.toPath(); | ||||
| 						} | ||||
| 					}) | ||||
| 					.forEach(modCompiles::add); | ||||
| 		} | ||||
| 
 | ||||
| 		for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { | ||||
| 			project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream().filter((f) -> !f.equals(input)).map(p -> { | ||||
| 				if (p.equals(input)) { | ||||
| 					return inputPath; | ||||
| 				} else { | ||||
| 					return p.toPath(); | ||||
| 				} | ||||
| 			}).forEach(modCompiles::add); | ||||
| 		} | ||||
| 
 | ||||
| 		project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")"); | ||||
| 
 | ||||
| 		TinyRemapper remapper = TinyRemapper.newRemapper() | ||||
| 			.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)) | ||||
| 			.build(); | ||||
| 		TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).build(); | ||||
| 
 | ||||
| 		try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) { | ||||
| 			outputConsumer.addNonClassFiles(inputPath); | ||||
|  | @ -178,12 +183,12 @@ public class ModProcessor { | |||
| 			remapper.finish(); | ||||
| 		} | ||||
| 
 | ||||
| 		if(!output.exists()){ | ||||
| 		if (!output.exists()) { | ||||
| 			throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath()); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	static void readInstallerJson(File file, Project project){ | ||||
| 	static void readInstallerJson(File file, Project project) { | ||||
| 		try { | ||||
| 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 			String launchMethod = extension.getLoaderLaunchMethod(); | ||||
|  | @ -193,8 +198,10 @@ public class ModProcessor { | |||
| 
 | ||||
| 			try (JarFile jarFile = new JarFile(file)) { | ||||
| 				ZipEntry entry = null; | ||||
| 
 | ||||
| 				if (!launchMethod.isEmpty()) { | ||||
| 					entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json"); | ||||
| 
 | ||||
| 					if (entry == null) { | ||||
| 						project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back"); | ||||
| 					} | ||||
|  | @ -203,6 +210,7 @@ public class ModProcessor { | |||
| 				if (entry == null) { | ||||
| 					entry = jarFile.getEntry("fabric-installer.json"); | ||||
| 					priority++; | ||||
| 
 | ||||
| 					if (entry == null) { | ||||
| 						return; | ||||
| 					} | ||||
|  |  | |||
|  | @ -24,28 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonObject; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.task.RemapJarTask; | ||||
| 
 | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.DependencySet; | ||||
| import org.gradle.api.artifacts.ProjectDependency; | ||||
| import org.gradle.api.tasks.bundling.AbstractArchiveTask; | ||||
| import org.zeroturnaround.zip.FileSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Path; | ||||
|  | @ -56,8 +34,28 @@ import java.util.Locale; | |||
| import java.util.Set; | ||||
| import java.util.zip.ZipEntry; | ||||
| 
 | ||||
| public class NestedJars { | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.zeroturnaround.zip.FileSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.DependencySet; | ||||
| import org.gradle.api.artifacts.ProjectDependency; | ||||
| import org.gradle.api.tasks.bundling.AbstractArchiveTask; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.task.RemapJarTask; | ||||
| 
 | ||||
| public class NestedJars { | ||||
| 	private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); | ||||
| 
 | ||||
| 	public static boolean addNestedJars(Project project, Path modJarPath) { | ||||
|  | @ -74,6 +72,7 @@ public class NestedJars { | |||
| 			protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||
| 				JsonObject json = GSON.fromJson(input, JsonObject.class); | ||||
| 				JsonArray nestedJars = json.getAsJsonArray("jars"); | ||||
| 
 | ||||
| 				if (nestedJars == null || !json.has("jars")) { | ||||
| 					nestedJars = new JsonArray(); | ||||
| 				} | ||||
|  | @ -96,6 +95,7 @@ public class NestedJars { | |||
| 
 | ||||
| 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | ||||
| 		DependencySet dependencies = configuration.getDependencies(); | ||||
| 
 | ||||
| 		for (Dependency dependency : dependencies) { | ||||
| 			if (dependency instanceof ProjectDependency) { | ||||
| 				ProjectDependency projectDependency = (ProjectDependency) dependency; | ||||
|  | @ -116,27 +116,32 @@ public class NestedJars { | |||
| 				fileList.addAll(prepareForNesting(configuration.files(dependency), dependency, project)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (File file : fileList) { | ||||
| 			if (!file.exists()) { | ||||
| 				throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (file.isDirectory() || !file.getName().endsWith(".jar")) { | ||||
| 				throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return fileList; | ||||
| 	} | ||||
| 
 | ||||
| 	//Looks for any deps that require a sub project to be built first | ||||
| 	public static List<RemapJarTask> getRequiredTasks(Project project){ | ||||
| 	public static List<RemapJarTask> getRequiredTasks(Project project) { | ||||
| 		List<RemapJarTask> remapTasks = new ArrayList<>(); | ||||
| 
 | ||||
| 		Configuration configuration = project.getConfigurations().getByName(Constants.INCLUDE); | ||||
| 		DependencySet dependencies = configuration.getDependencies(); | ||||
| 
 | ||||
| 		for (Dependency dependency : dependencies) { | ||||
| 			if (dependency instanceof ProjectDependency) { | ||||
| 				ProjectDependency projectDependency = (ProjectDependency) dependency; | ||||
| 				Project dependencyProject = projectDependency.getDependencyProject(); | ||||
| 
 | ||||
| 				for (Task task : dependencyProject.getTasksByName("remapJar", false)) { | ||||
| 					if (task instanceof RemapJarTask) { | ||||
| 						remapTasks.add((RemapJarTask) task); | ||||
|  | @ -144,29 +149,36 @@ public class NestedJars { | |||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return remapTasks; | ||||
| 	} | ||||
| 
 | ||||
| 	//This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library | ||||
| 	private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project){ | ||||
| 	private static List<File> prepareForNesting(Set<File> files, Dependency dependency, Project project) { | ||||
| 		List<File> fileList = new ArrayList<>(); | ||||
| 		for(File file : files){ | ||||
| 
 | ||||
| 		for (File file : files) { | ||||
| 			//A lib that doesnt have a mod.json, we turn it into a fake mod | ||||
| 			if(!ZipUtil.containsEntry(file, "fabric.mod.json")){ | ||||
| 			if (!ZipUtil.containsEntry(file, "fabric.mod.json")) { | ||||
| 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 				File tempDir = new File(extension.getUserCache(), "temp/modprocessing"); | ||||
| 				if(!tempDir.exists()){ | ||||
| 
 | ||||
| 				if (!tempDir.exists()) { | ||||
| 					tempDir.mkdirs(); | ||||
| 				} | ||||
| 
 | ||||
| 				File tempFile = new File(tempDir, file.getName()); | ||||
| 				if(tempFile.exists()){ | ||||
| 
 | ||||
| 				if (tempFile.exists()) { | ||||
| 					tempFile.delete(); | ||||
| 				} | ||||
| 
 | ||||
| 				try { | ||||
| 					FileUtils.copyFile(file, tempFile); | ||||
| 				} catch (IOException e) { | ||||
| 					throw new RuntimeException("Failed to copy file", e); | ||||
| 				} | ||||
| 
 | ||||
| 				ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency).getBytes()); | ||||
| 				fileList.add(tempFile); | ||||
| 			} else { | ||||
|  | @ -174,11 +186,12 @@ public class NestedJars { | |||
| 				fileList.add(file); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return fileList; | ||||
| 	} | ||||
| 
 | ||||
| 	//Generates a barebones mod for a dependency | ||||
| 	private static String getMod(Dependency dependency){ | ||||
| 	private static String getMod(Dependency dependency) { | ||||
| 		JsonObject jsonObject = new JsonObject(); | ||||
| 		jsonObject.addProperty("schemaVersion", 1); | ||||
| 		jsonObject.addProperty("id", (dependency.getGroup().replaceAll("\\.", "_") + "_" + dependency.getName()).toLowerCase(Locale.ENGLISH)); | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ package net.fabricmc.loom.util; | |||
| public class OperatingSystem { | ||||
| 	public static String getOS() { | ||||
| 		String osName = System.getProperty("os.name").toLowerCase(); | ||||
| 
 | ||||
| 		if (osName.contains("win")) { | ||||
| 			return "windows"; | ||||
| 		} else if (osName.contains("mac")) { | ||||
|  |  | |||
|  | @ -27,43 +27,43 @@ package net.fabricmc.loom.util; | |||
| import org.gradle.api.artifacts.ConfigurationContainer; | ||||
| 
 | ||||
| public class RemappedConfigurationEntry { | ||||
|     private final String sourceConfiguration; | ||||
|     private final String targetConfiguration; | ||||
|     private final String mavenScope; | ||||
|     private final boolean isOnModCompileClasspath; | ||||
| 	private final String sourceConfiguration; | ||||
| 	private final String targetConfiguration; | ||||
| 	private final String mavenScope; | ||||
| 	private final boolean isOnModCompileClasspath; | ||||
| 
 | ||||
|     public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { | ||||
|         this.sourceConfiguration = sourceConfiguration; | ||||
|         this.targetConfiguration = targetConfiguration; | ||||
|         this.isOnModCompileClasspath = isOnModCompileClasspath; | ||||
|         this.mavenScope = mavenScope; | ||||
|     } | ||||
| 	public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { | ||||
| 		this.sourceConfiguration = sourceConfiguration; | ||||
| 		this.targetConfiguration = targetConfiguration; | ||||
| 		this.isOnModCompileClasspath = isOnModCompileClasspath; | ||||
| 		this.mavenScope = mavenScope; | ||||
| 	} | ||||
| 
 | ||||
|     public String getMavenScope() { | ||||
|         return mavenScope; | ||||
|     } | ||||
| 	public String getMavenScope() { | ||||
| 		return mavenScope; | ||||
| 	} | ||||
| 
 | ||||
|     public boolean hasMavenScope() { | ||||
|         return mavenScope != null && !mavenScope.isEmpty(); | ||||
|     } | ||||
| 	public boolean hasMavenScope() { | ||||
| 		return mavenScope != null && !mavenScope.isEmpty(); | ||||
| 	} | ||||
| 
 | ||||
|     public boolean isOnModCompileClasspath() { | ||||
|         return isOnModCompileClasspath; | ||||
|     } | ||||
| 	public boolean isOnModCompileClasspath() { | ||||
| 		return isOnModCompileClasspath; | ||||
| 	} | ||||
| 
 | ||||
|     public String getSourceConfiguration() { | ||||
|         return sourceConfiguration; | ||||
|     } | ||||
| 	public String getSourceConfiguration() { | ||||
| 		return sourceConfiguration; | ||||
| 	} | ||||
| 
 | ||||
|     public String getRemappedConfiguration() { | ||||
|         return sourceConfiguration + "Mapped"; | ||||
|     } | ||||
| 	public String getRemappedConfiguration() { | ||||
| 		return sourceConfiguration + "Mapped"; | ||||
| 	} | ||||
| 
 | ||||
|     public String getTargetConfiguration(ConfigurationContainer container) { | ||||
|         if (container.findByName(targetConfiguration) == null) { | ||||
|             return "compile"; | ||||
|         } | ||||
| 	public String getTargetConfiguration(ConfigurationContainer container) { | ||||
| 		if (container.findByName(targetConfiguration) == null) { | ||||
| 			return "compile"; | ||||
| 		} | ||||
| 
 | ||||
|         return targetConfiguration; | ||||
|     } | ||||
| 		return targetConfiguration; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,21 +24,6 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.common.base.Strings; | ||||
| import com.google.common.collect.ImmutableList; | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.w3c.dom.Document; | ||||
| import org.w3c.dom.Element; | ||||
| import org.w3c.dom.Node; | ||||
| 
 | ||||
| import javax.xml.parsers.ParserConfigurationException; | ||||
| import javax.xml.transform.TransformerException; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
|  | @ -47,6 +32,23 @@ import java.util.List; | |||
| import java.util.Locale; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import javax.xml.parsers.ParserConfigurationException; | ||||
| import javax.xml.transform.TransformerException; | ||||
| 
 | ||||
| import com.google.common.base.Strings; | ||||
| import com.google.common.collect.ImmutableList; | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.w3c.dom.Document; | ||||
| import org.w3c.dom.Element; | ||||
| import org.w3c.dom.Node; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftProvider; | ||||
| 
 | ||||
| public class RunConfig { | ||||
| 	public String configName; | ||||
| 	public String projectName; | ||||
|  | @ -70,19 +72,23 @@ public class RunConfig { | |||
| 		if (!Strings.isNullOrEmpty(programArgs)) { | ||||
| 			this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); | ||||
| 		} | ||||
| 
 | ||||
| 		return root; | ||||
| 	} | ||||
| 
 | ||||
| 	public Element addXml(Node parent, String name, Map<String, String> values) { | ||||
| 		Document doc = parent.getOwnerDocument(); | ||||
| 
 | ||||
| 		if (doc == null) { | ||||
| 			doc = (Document) parent; | ||||
| 		} | ||||
| 
 | ||||
| 		Element e = doc.createElement(name); | ||||
| 
 | ||||
| 		for (Map.Entry<String, String> entry : values.entrySet()) { | ||||
| 			e.setAttribute(entry.getKey(), entry.getValue()); | ||||
| 		} | ||||
| 
 | ||||
| 		parent.appendChild(e); | ||||
| 		return e; | ||||
| 	} | ||||
|  | @ -90,29 +96,32 @@ public class RunConfig { | |||
| 	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { | ||||
| 		runConfig.projectName = project.getName(); | ||||
| 		runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | ||||
| 		runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath()  + "\""; | ||||
| 		runConfig.vmArgs = "-Dfabric.development=true -Djava.library.path=\"" + extension.getNativesDirectory().getAbsolutePath() + "\""; | ||||
| 
 | ||||
| 		switch (extension.getLoaderLaunchMethod()) { | ||||
| 			case "launchwrapper": | ||||
| 				runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; | ||||
| 				runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER); | ||||
| 				break; | ||||
| 			default: | ||||
| 				runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT); | ||||
| 				runConfig.programArgs = ""; | ||||
| 				break; | ||||
| 		case "launchwrapper": | ||||
| 			runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; | ||||
| 			runConfig.programArgs = "--tweakClass " + ("client".equals(mode) ? Constants.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.DEFAULT_FABRIC_SERVER_TWEAKER); | ||||
| 			break; | ||||
| 		default: | ||||
| 			runConfig.mainClass = "net.fabricmc.loader.launch.knot.Knot" + mode.substring(0, 1).toUpperCase(Locale.ROOT) + mode.substring(1).toLowerCase(Locale.ROOT); | ||||
| 			runConfig.programArgs = ""; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		// if installer.json found... | ||||
| 		JsonObject installerJson = extension.getInstallerJson(); | ||||
| 
 | ||||
| 		if (installerJson != null) { | ||||
| 			List<String> sideKeys = ImmutableList.of(mode, "common"); | ||||
| 
 | ||||
| 			// copy main class | ||||
| 			if (installerJson.has("mainClass")) { | ||||
| 				JsonElement mainClassJson = installerJson.get("mainClass"); | ||||
| 
 | ||||
| 				if (mainClassJson.isJsonObject()) { | ||||
| 					JsonObject mainClassesJson = mainClassJson.getAsJsonObject(); | ||||
| 
 | ||||
| 					for (String s : sideKeys) { | ||||
| 						if (mainClassesJson.has(s)) { | ||||
| 							runConfig.mainClass = mainClassesJson.get(s).getAsString(); | ||||
|  | @ -127,9 +136,11 @@ public class RunConfig { | |||
| 			// copy launchwrapper tweakers | ||||
| 			if (installerJson.has("launchwrapper")) { | ||||
| 				JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper"); | ||||
| 
 | ||||
| 				if (launchwrapperJson.has("tweakers")) { | ||||
| 					JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers"); | ||||
| 					StringBuilder builder = new StringBuilder(); | ||||
| 
 | ||||
| 					for (String s : sideKeys) { | ||||
| 						if (tweakersJson.has(s)) { | ||||
| 							for (JsonElement element : tweakersJson.getAsJsonArray(s)) { | ||||
|  | @ -137,15 +148,16 @@ public class RunConfig { | |||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					runConfig.programArgs += builder.toString(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public static RunConfig clientRunConfig(Project project){ | ||||
| 	public static RunConfig clientRunConfig(Project project) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MinecraftProvider minecraftProvider =  extension.getMinecraftProvider(); | ||||
| 		MinecraftProvider minecraftProvider = extension.getMinecraftProvider(); | ||||
| 		MinecraftVersionInfo minecraftVersionInfo = minecraftProvider.versionInfo; | ||||
| 
 | ||||
| 		RunConfig ideaClient = new RunConfig(); | ||||
|  | @ -157,7 +169,7 @@ public class RunConfig { | |||
| 		return ideaClient; | ||||
| 	} | ||||
| 
 | ||||
| 	public static RunConfig serverRunConfig(Project project){ | ||||
| 	public static RunConfig serverRunConfig(Project project) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 
 | ||||
| 		RunConfig ideaServer = new RunConfig(); | ||||
|  | @ -169,6 +181,7 @@ public class RunConfig { | |||
| 
 | ||||
| 	public String fromDummy(String dummy) throws IOException { | ||||
| 		String dummyConfig; | ||||
| 
 | ||||
| 		try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) { | ||||
| 			dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8); | ||||
| 		} | ||||
|  | @ -182,10 +195,11 @@ public class RunConfig { | |||
| 		return dummyConfig; | ||||
| 	} | ||||
| 
 | ||||
| 	public static String getOSClientJVMArgs(){ | ||||
| 		if(OperatingSystem.getOS().equalsIgnoreCase("osx")){ | ||||
| 	public static String getOSClientJVMArgs() { | ||||
| 		if (OperatingSystem.getOS().equalsIgnoreCase("osx")) { | ||||
| 			return " -XstartOnFirstThread"; | ||||
| 		} | ||||
| 
 | ||||
| 		return ""; | ||||
| 	} | ||||
| } | ||||
|  | @ -24,25 +24,27 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| public class SetupIntelijRunConfigs { | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MinecraftAssetsProvider; | ||||
| import net.fabricmc.loom.providers.MinecraftNativesProvider; | ||||
| 
 | ||||
| public class SetupIntelijRunConfigs { | ||||
| 	public static void setup(Project project) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 
 | ||||
| 		File projectDir = project.file(".idea"); | ||||
| 		if(!projectDir.exists()){ | ||||
| 
 | ||||
| 		if (!projectDir.exists()) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		try { | ||||
| 			generate(project); | ||||
| 		} catch (IOException e) { | ||||
|  | @ -50,6 +52,7 @@ public class SetupIntelijRunConfigs { | |||
| 		} | ||||
| 
 | ||||
| 		File runDir = new File(project.getRootDir(), extension.runDir); | ||||
| 
 | ||||
| 		if (!runDir.exists()) { | ||||
| 			runDir.mkdirs(); | ||||
| 		} | ||||
|  | @ -57,7 +60,7 @@ public class SetupIntelijRunConfigs { | |||
| 
 | ||||
| 	private static void generate(Project project) throws IOException { | ||||
| 		//Ensures the assets are downloaded when idea is syncing a project | ||||
| 		if(Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))){ | ||||
| 		if (Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))) { | ||||
| 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 			MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); | ||||
| 			MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); | ||||
|  | @ -68,18 +71,19 @@ public class SetupIntelijRunConfigs { | |||
| 		File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client.xml"); | ||||
| 		File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server.xml"); | ||||
| 
 | ||||
| 		if(!runConfigsDir.exists()){ | ||||
| 		if (!runConfigsDir.exists()) { | ||||
| 			runConfigsDir.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); | ||||
| 		String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); | ||||
| 
 | ||||
| 		if(!clientRunConfigs.exists()) | ||||
| 		if (!clientRunConfigs.exists()) { | ||||
| 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | ||||
| 		if(!serverRunConfigs.exists()) | ||||
| 		} | ||||
| 
 | ||||
| 		if (!serverRunConfigs.exists()) { | ||||
| 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | ||||
| 
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -24,31 +24,26 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.mappings.*; | ||||
| import net.fabricmc.stitch.util.Pair; | ||||
| import net.fabricmc.stitch.util.StitchUtil; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| 
 | ||||
| import org.cadixdev.lorenz.MappingSet; | ||||
| import org.cadixdev.lorenz.io.MappingsReader; | ||||
| import org.cadixdev.lorenz.io.TextMappingsReader; | ||||
| import org.cadixdev.lorenz.model.Mapping; | ||||
| import org.cadixdev.mercury.Mercury; | ||||
| import org.cadixdev.mercury.remapper.MercuryRemapper; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.internal.impldep.aQute.bnd.build.Run; | ||||
| import org.objectweb.asm.commons.Remapper; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.net.URI; | ||||
| import java.nio.file.*; | ||||
| import java.nio.file.attribute.BasicFileAttributes; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.providers.MappingsProvider; | ||||
| import net.fabricmc.mappings.ClassEntry; | ||||
| import net.fabricmc.mappings.EntryTriple; | ||||
| import net.fabricmc.mappings.FieldEntry; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import net.fabricmc.mappings.MethodEntry; | ||||
| import net.fabricmc.stitch.util.StitchUtil; | ||||
| 
 | ||||
| public class SourceRemapper { | ||||
| 	public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception { | ||||
|  | @ -79,11 +74,13 @@ public class SourceRemapper { | |||
| 			for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) { | ||||
| 				m.getClassPath().add(file.toPath()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!toNamed) { | ||||
| 				for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) { | ||||
| 					m.getClassPath().add(file.toPath()); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			for (Path file : extension.getUnmappedMods()) { | ||||
| 				if (Files.isRegularFile(file)) { | ||||
| 					m.getClassPath().add(file); | ||||
|  | @ -104,6 +101,7 @@ public class SourceRemapper { | |||
| 			} | ||||
| 
 | ||||
| 			source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar"); | ||||
| 
 | ||||
| 			try { | ||||
| 				com.google.common.io.Files.move(destination, source); | ||||
| 			} catch (IOException e) { | ||||
|  | @ -113,6 +111,7 @@ public class SourceRemapper { | |||
| 
 | ||||
| 		Path srcPath = source.toPath(); | ||||
| 		boolean isSrcTmp = false; | ||||
| 
 | ||||
| 		if (!source.isDirectory()) { | ||||
| 			// create tmp directory | ||||
| 			isSrcTmp = true; | ||||
|  | @ -144,27 +143,27 @@ public class SourceRemapper { | |||
| 		if (isSrcTmp) { | ||||
| 			Files.walkFileTree(srcPath, new DeletingFileVisitor()); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
|     private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { | ||||
|         Files.walk(from).forEach(path -> { | ||||
|             Path targetPath = to.resolve(from.relativize(path).toString()); | ||||
|             if (!isJavaFile(path) && !Files.exists(targetPath)) { | ||||
|                 try { | ||||
|                     Files.copy(path, targetPath); | ||||
|                 } catch (IOException e) { | ||||
|                     project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 	private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { | ||||
| 		Files.walk(from).forEach(path -> { | ||||
| 			Path targetPath = to.resolve(from.relativize(path).toString()); | ||||
| 
 | ||||
|     private static boolean isJavaFile(Path path) { | ||||
|         String name = path.getFileName().toString(); | ||||
|         // ".java" is not a valid java file | ||||
|         return name.endsWith(".java") && name.length() != 5; | ||||
|     } | ||||
| 			if (!isJavaFile(path) && !Files.exists(targetPath)) { | ||||
| 				try { | ||||
| 					Files.copy(path, targetPath); | ||||
| 				} catch (IOException e) { | ||||
| 					project.getLogger().warn("Could not copy non-java sources '" + source.getName() + "' fully!", e); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	private static boolean isJavaFile(Path path) { | ||||
| 		String name = path.getFileName().toString(); | ||||
| 		// ".java" is not a valid java file | ||||
| 		return name.endsWith(".java") && name.length() != 5; | ||||
| 	} | ||||
| 
 | ||||
| 	public static class TinyReader extends MappingsReader { | ||||
| 		private final Mappings m; | ||||
|  | @ -179,35 +178,27 @@ public class SourceRemapper { | |||
| 		@Override | ||||
| 		public MappingSet read(final MappingSet mappings) { | ||||
| 			for (ClassEntry entry : m.getClassEntries()) { | ||||
| 				mappings.getOrCreateClassMapping(entry.get(from)) | ||||
| 						.setDeobfuscatedName(entry.get(to)); | ||||
| 				mappings.getOrCreateClassMapping(entry.get(from)).setDeobfuscatedName(entry.get(to)); | ||||
| 			} | ||||
| 
 | ||||
| 			for (FieldEntry entry : m.getFieldEntries()) { | ||||
| 				EntryTriple fromEntry = entry.get(from); | ||||
| 				EntryTriple toEntry = entry.get(to); | ||||
| 
 | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()) | ||||
| 						.getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()) | ||||
| 						.setDeobfuscatedName(toEntry.getName()); | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||
| 			} | ||||
| 
 | ||||
| 			for (MethodEntry entry : m.getMethodEntries()) { | ||||
| 				EntryTriple fromEntry = entry.get(from); | ||||
| 				EntryTriple toEntry = entry.get(to); | ||||
| 
 | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()) | ||||
| 						.getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()) | ||||
| 						.setDeobfuscatedName(toEntry.getName()); | ||||
| 				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName()); | ||||
| 			} | ||||
| 
 | ||||
| 			return mappings; | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		public void close() throws IOException { | ||||
| 
 | ||||
| 		} | ||||
| 		public void close() throws IOException { } | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -24,63 +24,66 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.ref.SoftReference; | ||||
| import java.nio.file.*; | ||||
| import java.nio.file.FileSystems; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.StandardWatchEventKinds; | ||||
| import java.nio.file.WatchEvent; | ||||
| import java.nio.file.WatchKey; | ||||
| import java.nio.file.WatchService; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public final class StaticPathWatcher { | ||||
|     public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); | ||||
| 	public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); | ||||
| 
 | ||||
|     private final Map<Path, Boolean> changeCache = new HashMap<>(); | ||||
|     private final WatchService service; | ||||
|     private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); | ||||
| 	private final Map<Path, Boolean> changeCache = new HashMap<>(); | ||||
| 	private final WatchService service; | ||||
| 	private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); | ||||
| 
 | ||||
|     private StaticPathWatcher() { | ||||
|         try { | ||||
|             service = FileSystems.getDefault().newWatchService(); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
| 	private StaticPathWatcher() { | ||||
| 		try { | ||||
| 			service = FileSystems.getDefault().newWatchService(); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     public boolean hasFileChanged(Path filePath) { | ||||
|     	if(!Files.exists(filePath)){ | ||||
|     		return true; | ||||
| 	    } | ||||
|         WatchKey key; | ||||
|         while ((key = service.poll()) != null) { | ||||
|             for (WatchEvent<?> event : key.pollEvents()) { | ||||
|                 Object ctx = event.context(); | ||||
|                 if (ctx instanceof Path) { | ||||
|                     changeCache.put(((Path) ctx).toAbsolutePath(), true); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 	public boolean hasFileChanged(Path filePath) { | ||||
| 		if (!Files.exists(filePath)) { | ||||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
|         filePath = filePath.toAbsolutePath(); | ||||
|         Path parentPath = filePath.getParent(); | ||||
|         if (changeCache.containsKey(filePath)) { | ||||
|             return true; | ||||
|         } else { | ||||
|             if (!pathsObserved.containsKey(parentPath)) { | ||||
|                 try { | ||||
|                     pathsObserved.put(parentPath, parentPath.register( | ||||
|                             service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE | ||||
|                     )); | ||||
| 		WatchKey key; | ||||
| 
 | ||||
|                     return true; | ||||
|                 } catch (IOException e) { | ||||
|                     throw new RuntimeException(e); | ||||
|                 } | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 		while ((key = service.poll()) != null) { | ||||
| 			for (WatchEvent<?> event : key.pollEvents()) { | ||||
| 				Object ctx = event.context(); | ||||
| 
 | ||||
| 				if (ctx instanceof Path) { | ||||
| 					changeCache.put(((Path) ctx).toAbsolutePath(), true); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		filePath = filePath.toAbsolutePath(); | ||||
| 		Path parentPath = filePath.getParent(); | ||||
| 
 | ||||
| 		if (changeCache.containsKey(filePath)) { | ||||
| 			return true; | ||||
| 		} else { | ||||
| 			if (!pathsObserved.containsKey(parentPath)) { | ||||
| 				try { | ||||
| 					pathsObserved.put(parentPath, parentPath.register(service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE)); | ||||
| 
 | ||||
| 					return true; | ||||
| 				} catch (IOException e) { | ||||
| 					throw new RuntimeException(e); | ||||
| 				} | ||||
| 			} else { | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,14 +24,16 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.mappings.*; | ||||
| import net.fabricmc.mappings.ClassEntry; | ||||
| import net.fabricmc.mappings.EntryTriple; | ||||
| import net.fabricmc.mappings.FieldEntry; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import net.fabricmc.mappings.MethodEntry; | ||||
| import net.fabricmc.tinyremapper.IMappingProvider; | ||||
| import net.fabricmc.tinyremapper.MemberInstance; | ||||
| 
 | ||||
| public class TinyRemapperMappingsHelper { | ||||
| 	private TinyRemapperMappingsHelper() { | ||||
| 
 | ||||
| 	} | ||||
| 	private TinyRemapperMappingsHelper() { } | ||||
| 
 | ||||
| 	public static IMappingProvider create(Mappings mappings, String from, String to) { | ||||
| 		return (classMap, fieldMap, methodMap) -> { | ||||
|  |  | |||
|  | @ -25,7 +25,6 @@ | |||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| public class Version { | ||||
| 
 | ||||
| 	private String mappingsVersion; | ||||
| 	private String minecraftVersion; | ||||
| 
 | ||||
|  | @ -34,7 +33,7 @@ public class Version { | |||
| 	public Version(String version) { | ||||
| 		this.version = version; | ||||
| 
 | ||||
| 		if(version.contains("+build.")){ | ||||
| 		if (version.contains("+build.")) { | ||||
| 			this.minecraftVersion = version.substring(0, version.lastIndexOf('+')); | ||||
| 			this.mappingsVersion = version.substring(version.lastIndexOf('.') + 1); | ||||
| 		} else { | ||||
|  |  | |||
|  | @ -24,13 +24,13 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.util.progress; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| /** | ||||
|  * Wrapper to ProgressLogger internal API | ||||
|  * Wrapper to ProgressLogger internal API. | ||||
|  */ | ||||
| public class ProgressLogger { | ||||
| 	private final Object logger; | ||||
|  | @ -54,6 +54,7 @@ public class ProgressLogger { | |||
| 
 | ||||
| 	private static Class<?> getFactoryClass() { | ||||
| 		Class<?> progressLoggerFactoryClass = null; | ||||
| 
 | ||||
| 		try { | ||||
| 			//Gradle 2.14 and higher | ||||
| 			progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory"); | ||||
|  | @ -65,6 +66,7 @@ public class ProgressLogger { | |||
| 				// Unsupported Gradle version | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return progressLoggerFactoryClass; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -73,9 +75,10 @@ public class ProgressLogger { | |||
| 			try { | ||||
| 				return logger.getClass().getMethod(methodName, args); | ||||
| 			} catch (NoSuchMethodException ignored) { | ||||
| 
 | ||||
| 				//Nope | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -85,14 +88,15 @@ public class ProgressLogger { | |||
| 				method.setAccessible(true); | ||||
| 				return method.invoke(logger, args); | ||||
| 			} catch (IllegalAccessException | InvocationTargetException ignored) { | ||||
| 
 | ||||
| 				//Nope | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Get a Progress logger from the Gradle internal API | ||||
| 	 * Get a Progress logger from the Gradle internal API. | ||||
| 	 * | ||||
| 	 * @param project The project | ||||
| 	 * @param category The logger category | ||||
|  | @ -122,9 +126,9 @@ public class ProgressLogger { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * <p>Sets the description of the operation. This should be a full, stand-alone description of the operation. | ||||
| 	 * <p> | ||||
| 	 * <p>This must be called before {@link #started()}. | ||||
| 	 * Sets the description of the operation. This should be a full, stand-alone description of the operation. | ||||
| 	 * | ||||
| 	 * <p>This must be called before {@link #started()} | ||||
| 	 * | ||||
| 	 * @param description The description. | ||||
| 	 */ | ||||
|  | @ -143,8 +147,8 @@ public class ProgressLogger { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * <p>Sets the short description of the operation. This is used in place of the full description when display space is limited. | ||||
| 	 * <p> | ||||
| 	 * Sets the short description of the operation. This is used in place of the full description when display space is limited. | ||||
| 	 * | ||||
| 	 * <p>This must be called before {@link #started()} | ||||
| 	 * | ||||
| 	 * @param description The short description. | ||||
|  | @ -155,9 +159,9 @@ public class ProgressLogger { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * <p>Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||
| 	 * Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||
| 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | ||||
| 	 * <p> | ||||
| 	 * | ||||
| 	 * <p>If not specified, no logging header is logged. | ||||
| 	 * | ||||
| 	 * @return The logging header, possibly empty. | ||||
|  | @ -167,7 +171,7 @@ public class ProgressLogger { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * <p>Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||
| 	 * Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually | ||||
| 	 * also logged at the end of the operation, along with the final status message. Defaults to null. | ||||
| 	 * | ||||
| 	 * @param header The header. May be empty or null. | ||||
|  | @ -213,7 +217,7 @@ public class ProgressLogger { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Logs the completion of the operation, with no final status | ||||
| 	 * Logs the completion of the operation, with no final status. | ||||
| 	 */ | ||||
| 	public void completed() { | ||||
| 		invoke(completed); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue