├── .editorconfig ├── .gitattributes ├── .gitignore ├── HEADER ├── Jenkinsfile ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── src └── main ├── java └── net │ └── fabricmc │ └── loom │ ├── AbstractPlugin.java │ ├── LoomGradleExtension.java │ ├── LoomGradlePlugin.java │ ├── YarnGithubResolver.java │ ├── api │ └── decompilers │ │ ├── DecompilationMetadata.java │ │ └── LoomDecompiler.java │ ├── decompilers │ └── fernflower │ │ ├── AbstractFernFlowerDecompiler.java │ │ ├── AbstractForkedFFExecutor.java │ │ ├── FabricForkedFFExecutor.java │ │ ├── JavadocProvider.java │ │ ├── ThreadIDFFLogger.java │ │ ├── ThreadSafeResultSaver.java │ │ └── VineFlowerDecompiler.java │ ├── dependencies │ ├── ArtifactDependencyProvider.java │ ├── ArtifactInfo.java │ ├── ComputedDependency.java │ ├── DependencyGraph.java │ ├── DependencyProvider.java │ ├── LogicalDependencyProvider.java │ ├── LoomDependencyManager.java │ ├── PhysicalDependencyProvider.java │ └── RemappedConfigurationEntry.java │ ├── providers │ ├── JarNameFactory.java │ ├── JarNamingStrategy.java │ ├── LaunchProvider.java │ ├── LazyMappings.java │ ├── MappedModsCollector.java │ ├── MappedModsCollectors.java │ ├── MappedModsProvider.java │ ├── MappedModsResolver.java │ ├── MappingsCache.java │ ├── MappingsProvider.java │ ├── MinecraftAssetsProvider.java │ ├── MinecraftLibraryProvider.java │ ├── MinecraftMappedProvider.java │ ├── MinecraftNativesProvider.java │ ├── MinecraftProvider.java │ ├── MinecraftVersionAdaptable.java │ ├── SpecialCases.java │ ├── StackedMappingsProvider.java │ ├── mappings │ │ ├── DummyMapping.java │ │ ├── EnigmaReader.java │ │ ├── IMappingAcceptor.java │ │ ├── MappingBlob.java │ │ ├── TinyDuplicator.java │ │ ├── TinyReader.java │ │ ├── TinyV2toV1.java │ │ └── TinyWriter.java │ └── openfine │ │ ├── AccessChange.java │ │ ├── Annotator.java │ │ ├── ChangeSet.java │ │ ├── ClassReconstructor.java │ │ ├── EmptyMap.java │ │ ├── FieldChanges.java │ │ ├── FieldComparison.java │ │ ├── FinalityChange.java │ │ ├── Lambda.java │ │ ├── MethodChanges.java │ │ ├── MethodComparison.java │ │ ├── Openfine.java │ │ └── OptiFineVersion.java │ ├── task │ ├── AbstractLoomTask.java │ ├── AbstractRunTask.java │ ├── CleanLoomBinaries.java │ ├── CleanLoomMappings.java │ ├── DownloadAssetsTask.java │ ├── GenEclipseRunsTask.java │ ├── GenIdeaProjectTask.java │ ├── GenVsCodeProjectTask.java │ ├── GenerateSourcesTask.java │ ├── MigrateMappingsTask.java │ ├── RemapJarTask.java │ ├── RemapSourcesJarTask.java │ ├── RemappingJar.java │ ├── RunClientTask.java │ ├── RunServerTask.java │ └── lvt │ │ ├── ClassInfo.java │ │ ├── LocalTableRebuilder.java │ │ ├── RebuildLVTTask.java │ │ └── Verifier.java │ └── util │ ├── AccessTransformerHelper.java │ ├── Checksum.java │ ├── Closer.java │ ├── Constants.java │ ├── ConsumingOutputStream.java │ ├── DeletingFileVisitor.java │ ├── DownloadUtil.java │ ├── GradleSupport.java │ ├── GroovyXmlUtil.java │ ├── HexaFunction.java │ ├── LineNumberRemapper.java │ ├── ManifestVersion.java │ ├── MapJarsTiny.java │ ├── MinecraftVersionInfo.java │ ├── MixinRefmapHelper.java │ ├── NestedJars.java │ ├── OperatingSystem.java │ ├── RunConfig.java │ ├── SetupIntelijRunConfigs.java │ ├── SourceRemapper.java │ ├── StaticPathWatcher.java │ ├── ThrowingIntObjConsumer.java │ ├── TinyRemapperMappingsHelper.java │ ├── assets │ ├── AssetIndex.java │ └── AssetObject.java │ └── progress │ ├── ProgressLogger.java │ ├── ProgressLoggerImpl.java │ └── ProgressLoggerShim.java └── resources ├── eclipse_run_config_template.xml ├── idea_run_config_template.xml └── log4j2.fabric.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.kt] 2 | indent_style = tab 3 | 4 | [*.gradle] 5 | indent_style = tab -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | # 6 | # The above will handle all files NOT found below 7 | # 8 | # These files are text and should be normalized (Convert crlf => lf) 9 | *.css text 10 | *.df text 11 | *.htm text 12 | *.html text 13 | *.java text 14 | *.js text 15 | *.json text 16 | *.jsp text 17 | *.jspf text 18 | *.properties text 19 | *.sh text 20 | *.tld text 21 | *.txt text 22 | *.xml text 23 | 24 | # These files are binary and should be left untouched 25 | # (binary is a macro for -text -diff) 26 | *.class binary 27 | *.dll binary 28 | *.ear binary 29 | *.gif binary 30 | *.ico binary 31 | *.jar binary 32 | *.jpg binary 33 | *.jpeg binary 34 | *.png binary 35 | *.so binary 36 | *.war binary 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | /* 3 | 4 | # Folders 5 | !/gradle 6 | !/src 7 | 8 | # Files 9 | !/.gitattributes 10 | !/.gitignore 11 | !/.editorconfig 12 | !/build.gradle 13 | !/gradle.properties 14 | !/gradlew 15 | !/gradlew.bat 16 | !/HEADER 17 | !/LICENSE 18 | !/README.md 19 | !/settings.gradle 20 | !/Jenkinsfile 21 | !/.travis.yml 22 | !/checkstyle.xml -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | This file is part of fabric-loom, licensed under the MIT License (MIT). 2 | 3 | Copyright (c) 2016, 2017, 2018 FabricMC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | stage 'Checkout' 3 | 4 | checkout scm 5 | 6 | stage 'Build' 7 | 8 | sh "rm -rf build/libs/" 9 | sh "chmod +x gradlew" 10 | sh "./gradlew build -x test --refresh-dependencies" 11 | 12 | stage "Archive artifacts" 13 | 14 | sh "./gradlew publish" 15 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 FabricMC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | name = fabric-loom 2 | description = The Gradle plugin for Fabric 3 | url = https://github.com/FabricMC/fabric-loom -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chocohead/Fabric-Loom/2fc5f55141b9e420cf02d2af13bc697bca7f8c77/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Nov 03 23:12:45 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - mv build.gradle temp.gradle 3 | - gradle wrapper --gradle-version 6.1 --no-daemon --stacktrace 4 | - mv temp.gradle build.gradle -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = name 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/api/decompilers/DecompilationMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.api.decompilers; 26 | 27 | import java.nio.file.Path; 28 | import java.util.Collection; 29 | import java.util.Collections; 30 | import java.util.Map; 31 | 32 | import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; 33 | 34 | public class DecompilationMetadata { 35 | public final Map options; 36 | @Deprecated 37 | public final int numberOfThreads; 38 | public final boolean fork; 39 | public final Path javaDocs; 40 | public final Collection libraries; 41 | 42 | @Deprecated 43 | public DecompilationMetadata(int numberOfThreads, Path javaDocs, Collection libraries) { 44 | this(numberOfThreads, true, javaDocs, libraries); 45 | } 46 | 47 | @Deprecated 48 | public DecompilationMetadata(int numberOfThreads, boolean fork, Path javaDocs, Collection libraries) { 49 | this(Collections.singletonMap(IFernflowerPreferences.THREADS, numberOfThreads), fork, javaDocs, libraries); 50 | } 51 | 52 | public DecompilationMetadata(Map options, boolean fork, Path javaDocs, Collection libraries) { 53 | this.options = options; 54 | Object numberOfThreads = options.get(IFernflowerPreferences.THREADS); 55 | if (numberOfThreads instanceof Integer) { 56 | this.numberOfThreads = (Integer) numberOfThreads; 57 | } else { 58 | this.numberOfThreads = Runtime.getRuntime().availableProcessors(); 59 | } 60 | this.fork = fork; 61 | this.javaDocs = javaDocs; 62 | this.libraries = libraries; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/api/decompilers/LoomDecompiler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.api.decompilers; 26 | 27 | import java.nio.file.Path; 28 | 29 | import org.gradle.api.Project; 30 | import org.gradle.api.artifacts.ConfigurationContainer; 31 | 32 | public interface LoomDecompiler { 33 | String name(); 34 | 35 | default Object[] getClasspath(Project project) { 36 | ConfigurationContainer configurations = project.getBuildscript().getConfigurations(); 37 | return new Object[] {configurations.getByName("classpath"), configurations.detachedConfiguration(project.getDependencies().localGroovy())}; 38 | } 39 | 40 | /** 41 | * @param sourcesDestination Decompiled sources jar 42 | * @param linemapDestination A byproduct of decompilation that lines up the compiled jar's line numbers with the decompiled 43 | * sources jar for debugging. 44 | * A decompiler may not produce a linemap at all. 45 | * @param metaData Additional information that may or may not be needed while decompiling 46 | */ 47 | void decompile(Path compiledJar, Path sourcesDestination, Path linemapDestination, DecompilationMetadata metaData); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractForkedFFExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.decompilers.fernflower; 26 | 27 | import java.io.File; 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Objects; 33 | 34 | /** 35 | * Entry point for Forked FernFlower task. 36 | * Takes one parameter, a single file, each line is treated as command line input. 37 | * Forces one input file. 38 | * Forces one output file using '-o=/path/to/output' 39 | * Created by covers1624 on 11/02/19. 40 | *

Extending classes MUST have a standard "public static void main(args)". 41 | * They may then call AbstractForkedFFExecutor#decompile for it to use the overridden AbstractForkedFFExecutor#runFF 42 | *

43 | */ 44 | public abstract class AbstractForkedFFExecutor { 45 | public static void decompile(String[] args, AbstractForkedFFExecutor ffExecutor) { 46 | Map options = new HashMap<>(); 47 | File input = null; 48 | File output = null; 49 | File lineMap = null; 50 | File mappings = null; 51 | List libraries = new ArrayList<>(); 52 | 53 | boolean isOption = true; 54 | for (String arg : args) { 55 | if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { 56 | String value = arg.substring(5); 57 | 58 | if ("true".equalsIgnoreCase(value)) { 59 | value = "1"; 60 | } else if ("false".equalsIgnoreCase(value)) { 61 | value = "0"; 62 | } 63 | 64 | options.put(arg.substring(1, 4), value); 65 | } else { 66 | isOption = false; 67 | 68 | if (arg.startsWith("-e=")) { 69 | libraries.add(new File(arg.substring(3))); 70 | } else if (arg.startsWith("-o=")) { 71 | if (output != null) { 72 | throw new RuntimeException("Unable to set more than one output."); 73 | } 74 | 75 | output = new File(arg.substring(3)); 76 | } else if (arg.startsWith("-l=")) { 77 | if (lineMap != null) { 78 | throw new RuntimeException("Unable to set more than one lineMap file."); 79 | } 80 | 81 | lineMap = new File(arg.substring(3)); 82 | } else if (arg.startsWith("-m=")) { 83 | if (mappings != null) { 84 | throw new RuntimeException("Unable to use more than one mappings file."); 85 | } 86 | 87 | mappings = new File(arg.substring(3)); 88 | } else { 89 | if (input != null) { 90 | throw new RuntimeException("Unable to set more than one input."); 91 | } 92 | 93 | input = new File(arg); 94 | } 95 | } 96 | } 97 | 98 | Objects.requireNonNull(input, "Input not set."); 99 | Objects.requireNonNull(output, "Output not set."); 100 | Objects.requireNonNull(mappings, "Mappings not set."); 101 | 102 | ffExecutor.runFF(options, libraries, input, output, lineMap, mappings); 103 | } 104 | 105 | public abstract void runFF(Map options, List libraries, File input, File output, File lineMap, File mappings); 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricForkedFFExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.decompilers.fernflower; 26 | 27 | import java.io.File; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import org.jetbrains.java.decompiler.main.Fernflower; 32 | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; 33 | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger.Severity; 34 | import org.jetbrains.java.decompiler.main.extern.IResultSaver; 35 | 36 | import net.fabricmc.fernflower.api.IFabricJavadocProvider; 37 | 38 | public class FabricForkedFFExecutor extends AbstractForkedFFExecutor { 39 | public static void main(String[] args) { 40 | AbstractForkedFFExecutor.decompile(args, new FabricForkedFFExecutor()); 41 | } 42 | 43 | @Override 44 | public void runFF(Map options, List libraries, File input, File output, File lineMap, File mappings) { 45 | if (mappings.exists()) options.put(IFabricJavadocProvider.PROPERTY_NAME, new JavadocProvider(mappings)); 46 | 47 | IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); 48 | IFernflowerLogger logger = new ThreadIDFFLogger(System.out, System.err, false); 49 | Fernflower ff = new Fernflower(saver, options, logger); 50 | 51 | for (File library : libraries) { 52 | ff.addLibrary(library); 53 | } 54 | 55 | ff.addSource(input); 56 | logger.writeMessage("Decompiling jar...", Severity.INFO); 57 | try { 58 | ff.decompileContext(); 59 | } finally { 60 | ff.clearContext(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/decompilers/fernflower/JavadocProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.decompilers.fernflower; 9 | 10 | import java.io.File; 11 | import java.io.FileInputStream; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.util.ArrayList; 15 | import java.util.Comparator; 16 | import java.util.List; 17 | import java.util.Map; 18 | import java.util.Optional; 19 | import java.util.stream.Collectors; 20 | 21 | import org.jetbrains.java.decompiler.struct.StructClass; 22 | import org.jetbrains.java.decompiler.struct.StructField; 23 | import org.jetbrains.java.decompiler.struct.StructMethod; 24 | 25 | import net.fabricmc.fernflower.api.IFabricJavadocProvider; 26 | import net.fabricmc.mappings.EntryTriple; 27 | import net.fabricmc.mappings.MappingsProvider; 28 | import net.fabricmc.mappings.model.CommentEntry.Class; 29 | import net.fabricmc.mappings.model.CommentEntry.Field; 30 | import net.fabricmc.mappings.model.CommentEntry.Method; 31 | import net.fabricmc.mappings.model.CommentEntry.Parameter; 32 | import net.fabricmc.mappings.model.Comments; 33 | 34 | public class JavadocProvider implements IFabricJavadocProvider { 35 | private final Map> classComments; 36 | private final Map> methodComments; 37 | private final Map> paramComments; 38 | private final Map> fieldComments; 39 | 40 | public JavadocProvider(File mappings) { 41 | assert mappings.exists(); 42 | 43 | Comments comments; 44 | try (InputStream in = new FileInputStream(mappings)) { 45 | comments = MappingsProvider.readFullTinyMappings(in, true).getComments(); 46 | } catch (IOException e) { 47 | throw new RuntimeException("Error reading decompiler mappings at " + mappings, e); 48 | } 49 | 50 | classComments = comments.getClassComments().stream().collect(Collectors.toMap(Class::getClassName, Class::getComments)); 51 | methodComments = comments.getMethodComments().stream().collect(Collectors.toMap(Method::getMethod, Method::getComments)); 52 | paramComments = comments.getMethodParameterComments().stream().collect(Collectors.groupingBy(comment -> comment.getParameter().getMethod())); 53 | fieldComments = comments.getFieldComments().stream().collect(Collectors.toMap(Field::getField, Field::getComments)); 54 | } 55 | 56 | @Override 57 | public String getClassDoc(StructClass structClass) { 58 | return Optional.ofNullable(classComments.get(structClass.qualifiedName)).map(comments -> String.join("\n", comments)).orElse(null); 59 | } 60 | 61 | @Override 62 | public String getMethodDoc(StructClass structClass, StructMethod structMethod) { 63 | EntryTriple method = new EntryTriple(structClass.qualifiedName, structMethod.getName(), structMethod.getDescriptor()); 64 | List comment = methodComments.get(method); 65 | List params = paramComments.get(method); 66 | 67 | if (comment == null) { 68 | if (params == null) { 69 | return null; //No comment for the method or any of it's parameters 70 | } else { 71 | comment = new ArrayList<>(); //Only parameter comments 72 | } 73 | } else if (params != null) {//Both method and parameter comments 74 | comment = new ArrayList<>(comment); 75 | comment.add(""); //Leave space between the method comment and the parameter comment(s) 76 | } 77 | 78 | if (params != null) { 79 | params.sort(Comparator.comparingInt(param -> param.getParameter().getLocalVariableIndex())); 80 | 81 | for (Parameter param : params) { 82 | assert method.equals(param.getParameter().getMethod()); 83 | comment.add(String.format("@param %s %s", param.getParameter().getName(), String.join("\n\t", param.getComments()))); 84 | } 85 | } 86 | 87 | return String.join("\n", comment); 88 | } 89 | 90 | @Override 91 | public String getFieldDoc(StructClass structClass, StructField structField) { 92 | return Optional.ofNullable(fieldComments.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor()))).map(comments -> String.join("\n", comments)).orElse(null); 93 | } 94 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/decompilers/fernflower/ThreadIDFFLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.decompilers.fernflower; 26 | 27 | import java.io.PrintStream; 28 | import java.util.Stack; 29 | 30 | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; 31 | 32 | /** 33 | * This logger simply prints what each thread is doing 34 | * to the console in a machine parsable way. 35 | * 36 | *

Created by covers1624 on 11/02/19. 37 | */ 38 | public class ThreadIDFFLogger extends IFernflowerLogger { 39 | public final PrintStream stdOut; 40 | public final PrintStream stdErr; 41 | private final boolean watchMethods; 42 | 43 | private final ThreadLocal> workingClass = ThreadLocal.withInitial(Stack::new); 44 | private final ThreadLocal> line = ThreadLocal.withInitial(Stack::new); 45 | 46 | public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr, boolean watchMethods) { 47 | this.stdOut = stdOut; 48 | this.stdErr = stdErr; 49 | this.watchMethods = watchMethods; 50 | } 51 | 52 | private void pushMessage(Severity severity, String message) { 53 | line.get().push(severity.prefix + message); 54 | writeMessage(message, severity); 55 | } 56 | 57 | @Override 58 | public void writeMessage(String message, Severity severity) { 59 | long threadID = Thread.currentThread().getId(); 60 | stdOut.println(String.format("%d :: %s%s", threadID, severity.prefix, message).trim()); 61 | } 62 | 63 | @Override 64 | public void writeMessage(String message, Severity severity, Throwable t) { 65 | String currentClass = !workingClass.get().empty() ? workingClass.get().peek() : null; 66 | stdErr.println("Error thrown whilst " + (currentClass == null ? "out of class" : "in " + currentClass)); 67 | stdErr.println(message); 68 | t.printStackTrace(stdErr); 69 | } 70 | 71 | private void popMessage() { 72 | Stack stack = this.line.get(); 73 | stack.pop(); 74 | 75 | long threadID = Thread.currentThread().getId(); 76 | stdOut.println(String.format("%d :: %s", threadID, stack.empty() ? "waiting" : stack.peek()).trim()); 77 | } 78 | 79 | @Override 80 | public void startProcessingClass(String className) { 81 | workingClass.get().push(className); 82 | pushMessage(Severity.INFO, "Processing " + className); 83 | } 84 | 85 | @Override 86 | public void startReadingClass(String className) { 87 | workingClass.get().push(className); 88 | pushMessage(Severity.INFO, "Reading " + className); 89 | } 90 | 91 | @Override 92 | public void startClass(String className) { 93 | workingClass.get().push(className); 94 | pushMessage(Severity.INFO, "Decompiling " + className); 95 | } 96 | 97 | @Override 98 | public void startMethod(String methodName) { 99 | if (watchMethods) { 100 | String className = workingClass.get().peek(); 101 | pushMessage(Severity.INFO, "Decompiling " + className + '.' + methodName.substring(0, methodName.indexOf(' '))); 102 | } 103 | } 104 | 105 | @Override 106 | public void endMethod() { 107 | if (watchMethods) popMessage(); 108 | } 109 | 110 | @Override 111 | public void endClass() { 112 | popMessage(); 113 | workingClass.get().pop(); 114 | } 115 | 116 | @Override 117 | public void startWriteClass(String className) { 118 | pushMessage(Severity.INFO, "Writing " + className); 119 | } 120 | 121 | @Override 122 | public void endWriteClass() { 123 | popMessage(); 124 | } 125 | 126 | @Override 127 | public void endReadingClass() { 128 | popMessage(); 129 | workingClass.get().pop(); 130 | } 131 | 132 | @Override 133 | public void endProcessingClass() { 134 | popMessage(); 135 | workingClass.get().pop(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/decompilers/fernflower/VineFlowerDecompiler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.decompilers.fernflower; 26 | 27 | import org.gradle.api.Project; 28 | 29 | public class VineFlowerDecompiler extends AbstractFernFlowerDecompiler { 30 | public VineFlowerDecompiler(Project project) { 31 | super(project); 32 | } 33 | 34 | @Override 35 | public String name() { 36 | return "VineFlower"; 37 | } 38 | 39 | @Override 40 | public Class fernFlowerExecutor() { 41 | return FabricForkedFFExecutor.class; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/dependencies/ArtifactDependencyProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.dependencies; 9 | 10 | import java.util.function.Consumer; 11 | 12 | import org.gradle.api.GradleException; 13 | import org.gradle.api.InvalidUserDataException; 14 | import org.gradle.api.Project; 15 | import org.gradle.api.artifacts.Configuration; 16 | 17 | import net.fabricmc.loom.LoomGradleExtension; 18 | 19 | /** 20 | * A {@link DependencyProvider} which handles a resolved {@link Configuration} 21 | * 22 | * @author Chocohead 23 | * 24 | * @see PhysicalDependencyProvider 25 | */ 26 | public abstract class ArtifactDependencyProvider extends DependencyProvider { 27 | /** The name of the {@link Configuration} (as given by {@link Configuration#getName()}) that this handles */ 28 | public abstract String getTargetConfig(); 29 | 30 | /** Whether the target {@link Configuration} must have at least one dependency in */ 31 | public abstract boolean isRequired(); 32 | 33 | @Override 34 | protected final String getType() { 35 | return "artifact"; 36 | } 37 | 38 | @Override 39 | public final void provide(Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { 40 | Configuration configuration = project.getConfigurations().getByName(getTargetConfig()); 41 | 42 | if (isRequired() && configuration.getDependencies().isEmpty()) { 43 | throw new InvalidUserDataException("Missing dependency for " + configuration.getName() + " configuration"); 44 | } 45 | 46 | for (ArtifactInfo artifact : ArtifactInfo.resolve(configuration, project.getDependencies())) { 47 | try { 48 | provide(artifact, project, extension, postPopulationScheduler); 49 | } catch (Throwable t) { 50 | throw new GradleException(String.format("%s failed to provide %s for %s", getClass(), artifact.notation(), getTargetConfig()), t); 51 | } 52 | } 53 | } 54 | 55 | /** Perform whatever action this needs for the given {@link ArtifactInfo} from the target {@link Configuration} */ 56 | protected abstract void provide(ArtifactInfo artifact, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception; 57 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/dependencies/ComputedDependency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.dependencies; 9 | 10 | import java.io.File; 11 | import java.util.Collections; 12 | import java.util.Set; 13 | 14 | import org.gradle.api.artifacts.FileCollectionDependency; 15 | import org.gradle.api.artifacts.component.ComponentIdentifier; 16 | import org.gradle.api.file.FileCollection; 17 | import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInternal; 18 | import org.gradle.api.tasks.TaskDependency; 19 | 20 | //Gradle needs the internal interface to avoid class cast exceptions 21 | public abstract class ComputedDependency implements SelfResolvingDependencyInternal, FileCollectionDependency { 22 | private final String group, name, version; 23 | private String reason; 24 | 25 | public ComputedDependency(String group, String name, String version) { 26 | this.group = group; 27 | this.name = name; 28 | this.version = version; 29 | } 30 | 31 | @Override 32 | public String getGroup() { 33 | return group; 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | @Override 42 | public String getVersion() { 43 | return version; 44 | } 45 | 46 | @Override 47 | public ComponentIdentifier getTargetComponentId() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public void because(String reason) { 53 | this.reason = reason; 54 | } 55 | 56 | @Override 57 | public String getReason() { 58 | return reason; 59 | } 60 | 61 | @Override 62 | public TaskDependency getBuildDependencies() { 63 | return task -> Collections.emptySet(); 64 | } 65 | 66 | @Override 67 | public FileCollection getFiles() { 68 | resolve(); //Ensure the destination actually exists, as Gradle doesn't really care either way 69 | return makeFiles(); 70 | } 71 | 72 | protected abstract FileCollection makeFiles(); 73 | 74 | @Override 75 | public Set resolve(boolean transitive) { 76 | return resolve(); 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/dependencies/DependencyProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.dependencies; 26 | 27 | import java.io.File; 28 | import java.util.Collections; 29 | import java.util.Set; 30 | import java.util.function.Consumer; 31 | 32 | import org.gradle.api.Project; 33 | 34 | import net.fabricmc.loom.LoomGradleExtension; 35 | 36 | public abstract class DependencyProvider { 37 | private LoomDependencyManager dependencyManager; 38 | 39 | DependencyProvider() { 40 | } 41 | 42 | public void register(LoomDependencyManager dependencyManager) { 43 | this.dependencyManager = dependencyManager; 44 | } 45 | 46 | protected LoomDependencyManager getDependencyManager() { 47 | if (dependencyManager == null) throw new IllegalStateException("Unregistered dependency provider!"); 48 | return dependencyManager; 49 | } 50 | 51 | /** The collection of {@link DependencyProvider} types this depends on */ 52 | public Set> getDependencies() { 53 | return Collections.emptySet(); 54 | } 55 | 56 | /** The collection of {@link DependencyProvider} types this should run before */ 57 | public Set> getDependents() { 58 | return Collections.emptySet(); 59 | } 60 | 61 | protected abstract String getType(); 62 | 63 | /** Perform whatever action this needs once the dependencies have run and are all satisfied */ 64 | public abstract void provide(Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception; 65 | 66 | protected T getProvider(Class type) { 67 | T provider = getDependencyManager().getProvider(type); 68 | if (provider == null) throw new IllegalArgumentException("Could not find " + type + " instance!"); 69 | return provider; 70 | } 71 | 72 | protected void addDependency(String module, Project project, String target) { 73 | addDependency(project.getDependencies().module(module), project, target); 74 | } 75 | 76 | protected void addDependency(File file, Project project, String target) { 77 | addDependency(project.files(file), project, target); 78 | } 79 | 80 | private void addDependency(Object object, Project project, String target) { 81 | project.getDependencies().add(target, object); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/dependencies/LogicalDependencyProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.dependencies; 9 | 10 | import java.util.Set; 11 | 12 | /** 13 | * A {@link DependencyProvider} which waits for and runs after other {@link DependencyProvider}s 14 | * 15 | * @author Chocohead 16 | */ 17 | public abstract class LogicalDependencyProvider extends DependencyProvider { 18 | @Override 19 | protected final String getType() { 20 | return "logical"; 21 | } 22 | 23 | @Override 24 | public abstract Set> getDependencies(); 25 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/dependencies/RemappedConfigurationEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.dependencies; 26 | 27 | import org.gradle.api.artifacts.Configuration; 28 | import org.gradle.api.artifacts.ConfigurationContainer; 29 | import org.gradle.api.plugins.JavaPlugin; 30 | 31 | public class RemappedConfigurationEntry { 32 | private final String sourceConfiguration; 33 | private final String targetConfiguration; 34 | private final String mavenScope; 35 | private final boolean isOnModCompileClasspath; 36 | 37 | public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { 38 | this.sourceConfiguration = sourceConfiguration; 39 | this.targetConfiguration = targetConfiguration; 40 | this.isOnModCompileClasspath = isOnModCompileClasspath; 41 | this.mavenScope = mavenScope; 42 | } 43 | 44 | public String getMavenScope() { 45 | return mavenScope; 46 | } 47 | 48 | public boolean hasMavenScope() { 49 | return mavenScope != null && !mavenScope.isEmpty(); 50 | } 51 | 52 | public boolean isOnModCompileClasspath() { 53 | return isOnModCompileClasspath; 54 | } 55 | 56 | public String getSourceConfiguration() { 57 | return sourceConfiguration; 58 | } 59 | 60 | public String getRemappedConfiguration() { 61 | return sourceConfiguration + "Mapped"; 62 | } 63 | 64 | public Configuration getTargetConfiguration(ConfigurationContainer container) { 65 | Configuration out = container.findByName(targetConfiguration); 66 | return out != null ? out : container.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/JarNameFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | /** We're one strategy away from being proper enterprise Java code */ 11 | public enum JarNameFactory { 12 | CLIENT { 13 | @Override 14 | public String getDependencyName(JarNamingStrategy strategy) { 15 | return strategy.getVersion().concat("-client"); 16 | } 17 | }, 18 | CLIENT_INTERMEDIARY { 19 | @Override 20 | public String getDependencyName(JarNamingStrategy strategy) { 21 | return strategy.getVersion().concat("-client-intermediary"); 22 | } 23 | }, 24 | SERVER { 25 | @Override 26 | public String getDependencyName(JarNamingStrategy strategy) { 27 | return strategy.getVersion().concat("-server"); 28 | } 29 | }, 30 | SERVER_INTERMEDIARY { 31 | @Override 32 | public String getDependencyName(JarNamingStrategy strategy) { 33 | return strategy.getVersion().concat("-server-intermediary"); 34 | } 35 | }, 36 | MERGED { 37 | @Override 38 | public String getDependencyName(JarNamingStrategy strategy) { 39 | return strategy.getVersion().concat("-merged"); 40 | } 41 | }, 42 | MERGED_INTERMEDIARY { 43 | @Override 44 | public String getDependencyName(JarNamingStrategy strategy) { 45 | return strategy.getVersion() + "-intermediary" + strategy.getExtra(); //FIXME: Attach the mapping name to the end? 46 | } 47 | }, 48 | NAMED { 49 | @Override 50 | public String getDependencyName(JarNamingStrategy strategy) { 51 | return strategy.getVersion() + "-mapped" + strategy.getExtra() + '-' + strategy.getMappings(); 52 | } 53 | }; 54 | 55 | public abstract String getDependencyName(JarNamingStrategy strategy); 56 | 57 | public String getJarName(JarNamingStrategy strategy) { 58 | return "minecraft-" + getDependencyName(strategy) + ".jar"; 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/JarNamingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | public final class JarNamingStrategy { 11 | private final String version, mappings, extra; 12 | 13 | private JarNamingStrategy(String version, String mappings, String extra) { 14 | this.version = version; 15 | this.mappings = mappings; 16 | this.extra = extra; 17 | } 18 | 19 | public static JarNamingStrategy forVersion(String version) { 20 | if (version == null) throw new IllegalArgumentException("Null version"); 21 | return new JarNamingStrategy(version, null, null); 22 | } 23 | 24 | public JarNamingStrategy withMappings(String mappings) { 25 | if (mappings == null) throw new IllegalArgumentException("Null mappings"); 26 | return new JarNamingStrategy(version, mappings, extra); 27 | } 28 | 29 | public JarNamingStrategy withExtra(String extra) { 30 | if (extra == null) throw new IllegalArgumentException("Null extra"); 31 | return new JarNamingStrategy(version, mappings, extra); 32 | } 33 | 34 | public String getVersion() { 35 | return version; 36 | } 37 | 38 | public String getMappings() { 39 | if (mappings == null) throw new UnsupportedOperationException("Strategy does not support mappings"); 40 | return mappings; 41 | } 42 | 43 | public String getExtra() { 44 | return extra != null ? extra : ""; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "NamingStrategy[version = " + version + (mappings != null ? ", mappings = " + mappings : "") + (extra != null ? ", extra = " + extra : "") + ']'; 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/LazyMappings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | import java.io.IOException; 11 | import java.nio.file.Path; 12 | 13 | import net.fabricmc.loom.providers.LazyMappings.ActiveMappings; 14 | 15 | interface LazyMappings { 16 | interface ActiveMappings extends AutoCloseable { 17 | Path getMappings(); 18 | 19 | @Override 20 | default void close() throws IOException { 21 | } 22 | } 23 | 24 | ActiveMappings open() throws IOException; 25 | } 26 | 27 | final class DirectMappings implements ActiveMappings { 28 | private final Path mappings; 29 | 30 | public DirectMappings(Path mappings) { 31 | this.mappings = mappings; 32 | } 33 | 34 | @Override 35 | public Path getMappings() { 36 | return mappings; 37 | } 38 | 39 | @Override 40 | public void close() { 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MappedModsCollector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | import java.util.function.Consumer; 11 | import java.util.function.Function; 12 | 13 | import org.gradle.api.Project; 14 | import org.gradle.api.artifacts.Configuration; 15 | import org.gradle.api.artifacts.ConfigurationContainer; 16 | 17 | import net.fabricmc.loom.LoomGradleExtension; 18 | import net.fabricmc.loom.dependencies.ArtifactDependencyProvider; 19 | import net.fabricmc.loom.dependencies.ArtifactInfo; 20 | import net.fabricmc.loom.dependencies.LoomDependencyManager; 21 | import net.fabricmc.loom.dependencies.RemappedConfigurationEntry; 22 | 23 | public abstract class MappedModsCollector extends ArtifactDependencyProvider { 24 | private final String originConfig, remappedConfig; 25 | private final Function naturalConfig; 26 | private MappedModsResolver resolver; 27 | 28 | public MappedModsCollector(RemappedConfigurationEntry configuration) { 29 | originConfig = configuration.getSourceConfiguration(); 30 | naturalConfig = configuration::getTargetConfiguration; 31 | remappedConfig = configuration.getRemappedConfiguration(); 32 | } 33 | 34 | public MappedModsCollector(String originConfig, String naturalConfig, String remappedConfig) { 35 | this.originConfig = originConfig; 36 | this.naturalConfig = configs -> configs.getByName(naturalConfig); 37 | this.remappedConfig = remappedConfig; 38 | } 39 | 40 | @Override 41 | public void register(LoomDependencyManager dependencyManager) { 42 | super.register(dependencyManager); 43 | 44 | if (!dependencyManager.hasProvider(MappedModsResolver.class)) { 45 | dependencyManager.addProvider(resolver = new MappedModsResolver()); 46 | } else { 47 | resolver = dependencyManager.getProvider(MappedModsResolver.class); 48 | } 49 | } 50 | 51 | @Override 52 | public String getTargetConfig() { 53 | return originConfig; 54 | } 55 | 56 | @Override 57 | public boolean isRequired() { 58 | return false; 59 | } 60 | 61 | @Override 62 | protected void provide(ArtifactInfo artifact, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { 63 | if (!artifact.isFabricMod()) { 64 | project.getLogger().lifecycle(":providing {}", artifact.notation()); 65 | naturalConfig.apply(project.getConfigurations()).getDependencies().add(artifact.asNonTransitiveDependency()); 66 | } else { 67 | resolver.queueMod(remappedConfig, artifact); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MappedModsCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | import java.util.Set; 11 | 12 | import com.google.common.collect.ImmutableSet; 13 | 14 | import net.fabricmc.loom.dependencies.LoomDependencyManager; 15 | import net.fabricmc.loom.util.Constants; 16 | 17 | public final class MappedModsCollectors { 18 | private MappedModsCollectors() { 19 | } 20 | 21 | public static Set> all() { 22 | return ImmutableSet.of(ModCompile.class, ModApi.class, ModImplementation.class, ModRuntime.class, ModCompileOnly.class); 23 | } 24 | 25 | public static void addAll(LoomDependencyManager dependencyManager) { 26 | dependencyManager.addProvider(new ModCompile()); 27 | dependencyManager.addProvider(new ModApi()); 28 | dependencyManager.addProvider(new ModImplementation()); 29 | dependencyManager.addProvider(new ModRuntime()); 30 | dependencyManager.addProvider(new ModCompileOnly()); 31 | } 32 | 33 | public static class ModCompile extends MappedModsCollector { 34 | public ModCompile() { 35 | super(Constants.MOD_COMPILE); 36 | } 37 | } 38 | 39 | public static class ModApi extends MappedModsCollector { 40 | public ModApi() { 41 | super(Constants.MOD_API); 42 | } 43 | } 44 | 45 | public static class ModImplementation extends MappedModsCollector { 46 | public ModImplementation() { 47 | super(Constants.MOD_IMPLEMENTATION); 48 | } 49 | } 50 | 51 | public static class ModRuntime extends MappedModsCollector { 52 | public ModRuntime() { 53 | super(Constants.MOD_RUNTIME); 54 | } 55 | } 56 | 57 | public static class ModCompileOnly extends MappedModsCollector { 58 | public ModCompileOnly() { 59 | super(Constants.MOD_COMPILE_ONLY); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MappingsCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.providers; 26 | 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.lang.ref.SoftReference; 30 | import java.nio.file.Files; 31 | import java.nio.file.Path; 32 | import java.util.HashMap; 33 | import java.util.Map; 34 | 35 | import net.fabricmc.loom.util.StaticPathWatcher; 36 | import net.fabricmc.mappings.Mappings; 37 | import net.fabricmc.mappings.MappingsProvider; 38 | 39 | public final class MappingsCache { 40 | public static final MappingsCache INSTANCE = new MappingsCache(); 41 | 42 | private final Map> mappingsCache = new HashMap<>(); 43 | 44 | private MappingsCache() { 45 | } 46 | 47 | //TODO: loom doesn't actually use new mappings when the mappings change until the Gradle daemons are stopped 48 | public Mappings get(Path mappingsPath) throws IOException { 49 | mappingsPath = mappingsPath.toAbsolutePath(); 50 | 51 | SoftReference ref = !StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath) ? mappingsCache.get(mappingsPath) : null; 52 | Mappings mappings = ref != null ? ref.get() : null; 53 | 54 | if (mappings == null) { 55 | try (InputStream stream = Files.newInputStream(mappingsPath)) { 56 | mappings = MappingsProvider.readTinyMappings(stream, false); 57 | mappingsCache.put(mappingsPath, new SoftReference<>(mappings)); 58 | } 59 | 60 | StaticPathWatcher.INSTANCE.resetFile(mappingsPath); 61 | } 62 | 63 | return mappings; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MinecraftAssetsProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.providers; 26 | 27 | import java.io.File; 28 | import java.io.FileReader; 29 | import java.io.IOException; 30 | import java.net.URL; 31 | import java.util.Deque; 32 | import java.util.Map; 33 | import java.util.concurrent.ConcurrentLinkedDeque; 34 | import java.util.concurrent.ExecutorService; 35 | import java.util.concurrent.Executors; 36 | import java.util.concurrent.TimeUnit; 37 | 38 | import com.google.gson.Gson; 39 | import org.gradle.api.GradleException; 40 | import org.gradle.api.Project; 41 | 42 | import net.fabricmc.loom.LoomGradleExtension; 43 | import net.fabricmc.loom.util.Checksum; 44 | import net.fabricmc.loom.util.Constants; 45 | import net.fabricmc.loom.util.DownloadUtil; 46 | import net.fabricmc.loom.util.MinecraftVersionInfo; 47 | import net.fabricmc.loom.util.assets.AssetIndex; 48 | import net.fabricmc.loom.util.assets.AssetObject; 49 | import net.fabricmc.loom.util.progress.ProgressLogger; 50 | 51 | public class MinecraftAssetsProvider { 52 | public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { 53 | LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); 54 | boolean offline = project.getGradle().getStartParameter().isOffline(); 55 | 56 | MinecraftVersionInfo.AssetIndex assetIndex = minecraftProvider.getAssetIndex(); 57 | 58 | // get existing cache files 59 | File assets = new File(extension.getUserCache(), "assets"); 60 | 61 | if (!assets.exists()) { 62 | assets.mkdirs(); 63 | } 64 | 65 | File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.minecraftVersion) + ".json"); 66 | 67 | if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.hash)) { 68 | project.getLogger().lifecycle(":downloading asset index"); 69 | 70 | if (offline) { 71 | if (assetsInfo.exists()) { 72 | //We know it's outdated but can't do anything about it, oh well 73 | project.getLogger().warn("Asset index outdated"); 74 | } else { 75 | //We don't know what assets we need, just that we don't have any 76 | throw new GradleException("Asset index not found at " + assetsInfo.getAbsolutePath()); 77 | } 78 | } else { 79 | DownloadUtil.downloadIfChanged(assetIndex.url, assetsInfo, project.getLogger()); 80 | } 81 | } 82 | 83 | project.getLogger().lifecycle(":downloading assets..."); 84 | 85 | Deque loggers = new ConcurrentLinkedDeque<>(); 86 | ExecutorService executor = Executors.newFixedThreadPool(Math.min(10, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1))); 87 | 88 | AssetIndex index; 89 | 90 | try (FileReader fileReader = new FileReader(assetsInfo)) { 91 | index = new Gson().fromJson(fileReader, AssetIndex.class); 92 | } 93 | 94 | Map parent = index.getFileMap(); 95 | 96 | for (Map.Entry entry : parent.entrySet()) { 97 | AssetObject object = entry.getValue(); 98 | String sha1 = object.getHash(); 99 | String filename = "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1; 100 | File file = new File(assets, filename); 101 | 102 | if (!file.exists() || !Checksum.equals(file, sha1)) { 103 | if (offline) { 104 | if (file.exists()) { 105 | project.getLogger().warn("Outdated asset " + entry.getKey()); 106 | } else { 107 | throw new GradleException("Asset " + entry.getKey() + " not found at " + file.getAbsolutePath()); 108 | } 109 | } else { 110 | executor.execute(() -> { 111 | ProgressLogger progressLogger; 112 | 113 | if (loggers.isEmpty()) { 114 | //Create a new logger if we need one 115 | progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); 116 | progressLogger.start("Downloading assets...", "assets"); 117 | } else { 118 | // use a free logger if we can 119 | progressLogger = loggers.pop(); 120 | } 121 | 122 | String assetName = entry.getKey(); 123 | int end = assetName.lastIndexOf("/") + 1; 124 | 125 | if (end > 0) { 126 | assetName = assetName.substring(end); 127 | } 128 | 129 | project.getLogger().debug(":downloading asset " + assetName); 130 | progressLogger.progress(String.format("%-30.30s", assetName) + " - " + sha1); 131 | 132 | try { 133 | DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); 134 | } catch (IOException e) { 135 | throw new RuntimeException("Failed to download: " + assetName, e); 136 | } 137 | 138 | //Give this logger back 139 | loggers.add(progressLogger); 140 | }); 141 | } 142 | } 143 | } 144 | 145 | //Wait for the assets to all download 146 | executor.shutdown(); 147 | 148 | try { 149 | if (executor.awaitTermination(2, TimeUnit.HOURS)) { 150 | executor.shutdownNow(); 151 | } 152 | } catch (InterruptedException e) { 153 | throw new RuntimeException(e); 154 | } 155 | 156 | loggers.forEach(ProgressLogger::completed); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MinecraftLibraryProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.providers; 26 | 27 | import java.io.File; 28 | import java.util.ArrayList; 29 | import java.util.Collections; 30 | import java.util.List; 31 | import java.util.Set; 32 | import java.util.function.Consumer; 33 | import java.util.function.Predicate; 34 | 35 | import org.gradle.api.Project; 36 | 37 | import net.fabricmc.loom.LoomGradleExtension; 38 | import net.fabricmc.loom.dependencies.DependencyProvider; 39 | import net.fabricmc.loom.dependencies.LogicalDependencyProvider; 40 | import net.fabricmc.loom.util.Constants; 41 | import net.fabricmc.loom.util.GradleSupport; 42 | import net.fabricmc.loom.util.MinecraftVersionInfo.Library; 43 | 44 | public class MinecraftLibraryProvider extends LogicalDependencyProvider { 45 | final List natives = new ArrayList<>(); 46 | private Set libs = Collections.emptySet(); 47 | private boolean hasLWJGL2; 48 | 49 | @Override 50 | public Set> getDependencies() { 51 | return Collections.singleton(MinecraftProvider.class); 52 | } 53 | 54 | @Override 55 | public void provide(Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { 56 | MinecraftProvider minecraftProvider = getProvider(MinecraftProvider.class); 57 | Predicate filter = extension.getLibraryFilters(); 58 | boolean lwjgl2 = false; 59 | 60 | for (Library library : minecraftProvider.getLibraries()) { 61 | if (library.willUse() && filter.test(library.getArtifactName())) { 62 | if (!library.isNative()) { 63 | addDependency(library.getArtifactName(), project, Constants.MINECRAFT_LIBRARIES); 64 | lwjgl2 |= library.name.startsWith("org.lwjgl.lwjgl:lwjgl:2."); 65 | } else { 66 | natives.add(library); 67 | } 68 | } 69 | } 70 | 71 | if (!extractNatives(project) && !lwjgl2) { 72 | for (Library library : natives) { 73 | addDependency(library.getArtifactName(), project, Constants.MINECRAFT_LIBRARIES); 74 | } 75 | natives.clear(); 76 | } 77 | 78 | hasLWJGL2 = lwjgl2; 79 | libs = project.getConfigurations().getByName(Constants.MINECRAFT_LIBRARIES).getFiles(); 80 | } 81 | 82 | private static boolean extractNatives(Project project) { 83 | int major = GradleSupport.majorGradleVersion(project); 84 | return major > 5 || major == 5 && GradleSupport.minorGradleVersion(project) >= 6 && GradleSupport.patchGradleVersion(project) >= 3; 85 | } 86 | 87 | public Set getLibraries() { 88 | return Collections.unmodifiableSet(libs); 89 | } 90 | 91 | public boolean extractNatives() { 92 | return !natives.isEmpty(); 93 | } 94 | 95 | public boolean hasLWJGL2() { 96 | return hasLWJGL2; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.providers; 26 | 27 | import java.io.File; 28 | import java.util.Collection; 29 | import java.util.Collections; 30 | import java.util.Set; 31 | import java.util.function.Consumer; 32 | 33 | import org.gradle.api.Project; 34 | 35 | import com.google.common.collect.ImmutableSet; 36 | import com.google.common.io.Files; 37 | 38 | import net.fabricmc.loom.LoomGradleExtension; 39 | import net.fabricmc.loom.dependencies.DependencyProvider; 40 | import net.fabricmc.loom.dependencies.LogicalDependencyProvider; 41 | import net.fabricmc.loom.providers.openfine.Openfine; 42 | import net.fabricmc.loom.util.AccessTransformerHelper; 43 | import net.fabricmc.loom.util.Constants; 44 | import net.fabricmc.loom.util.MapJarsTiny; 45 | import net.fabricmc.stitch.util.Pair; 46 | 47 | public class MinecraftMappedProvider extends LogicalDependencyProvider { 48 | public File MINECRAFT_MAPPED_JAR; 49 | public File MINECRAFT_INTERMEDIARY_JAR; 50 | 51 | @Override 52 | public Set> getDependencies() { 53 | return ImmutableSet.of(MinecraftProvider.class, MinecraftLibraryProvider.class, MappingsProvider.class); 54 | } 55 | 56 | @Override 57 | public void provide(Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { 58 | MinecraftProvider minecraftProvider = getProvider(MinecraftProvider.class); 59 | MappingsProvider mappingsProvider = getProvider(MappingsProvider.class); 60 | 61 | if (!mappingsProvider.MAPPINGS_TINY.exists()) { 62 | throw new RuntimeException("mappings file not found"); 63 | } 64 | 65 | if (java.nio.file.Files.notExists(minecraftProvider.getMergedJar())) { 66 | throw new RuntimeException("input merged jar not found"); 67 | } 68 | 69 | JarNamingStrategy jarName = minecraftProvider.makeNamingStrategy(); //Explicitly flag AT'd jars differently to vanilla/stock ones 70 | File cache; //Save to the project cache when ATing to simplify flagging AT changes 71 | Set> targets; 72 | boolean atChange = false; 73 | if (extension.hasAT()) { 74 | jarName = jarName.withExtra("-transformed"); 75 | cache = new File(extension.getRootProjectPersistentCache(), "access_transformed_jars"); 76 | cache.mkdir(); 77 | 78 | //Add the transformed jars repo so that Gradle can find Minecraft 79 | project.getRepositories().flatDir(repo -> { 80 | repo.setName("AccessTransformedJars"); 81 | repo.dir(cache); 82 | }); 83 | 84 | project.getLogger().info("Negotiating access transformations..."); 85 | targets = AccessTransformerHelper.loadATs(extension.getAT()); 86 | project.getLogger().info("Access transformations solved for " + targets.size() + " targets"); 87 | 88 | File lastAT = new File(cache, "last-seen.at"); 89 | if (lastAT.exists() ? !AccessTransformerHelper.loadATs(lastAT).equals(targets) : !targets.isEmpty()) { 90 | Files.copy(extension.getAT(), lastAT); //Replace the old with the new 91 | atChange = true; 92 | } 93 | } else { 94 | cache = extension.getUserCache(); 95 | targets = Collections.emptySet(); 96 | } 97 | 98 | MINECRAFT_INTERMEDIARY_JAR = new File(cache, JarNameFactory.MERGED_INTERMEDIARY.getJarName(jarName)); 99 | MINECRAFT_MAPPED_JAR = new File(cache, JarNameFactory.NAMED.getJarName(jarName)); 100 | 101 | if (!getMappedJar().exists() || !getIntermediaryJar().exists() || atChange) { 102 | if (getMappedJar().exists()) { 103 | getMappedJar().delete(); 104 | } 105 | if (getIntermediaryJar().exists() && !minecraftProvider.getMergedJar().equals(getIntermediaryJar().toPath())) { 106 | getIntermediaryJar().delete(); 107 | } 108 | if (extension.hasOptiFine()) Openfine.applyBonusMappings(mappingsProvider); 109 | MapJarsTiny.mapJars(minecraftProvider, this, project); 110 | if (!targets.isEmpty()) MapJarsTiny.transform(project, targets, this, mappingsProvider); 111 | if (extension.hasOptiFine()) Openfine.transformRemovals(project.getLogger(), mappingsProvider, getMappedJar()); 112 | } 113 | 114 | if (!MINECRAFT_MAPPED_JAR.exists()) { 115 | throw new RuntimeException("mapped jar not found"); 116 | } 117 | 118 | addDependency("net.minecraft:minecraft:".concat(JarNameFactory.NAMED.getDependencyName(jarName)), project, Constants.MINECRAFT_NAMED); 119 | addDependency("net.minecraft:minecraft:".concat(JarNameFactory.MERGED_INTERMEDIARY.getDependencyName(jarName)), project, Constants.MINECRAFT_INTERMEDIARY); 120 | } 121 | 122 | public Collection getMapperPaths() { 123 | return getProvider(MinecraftLibraryProvider.class).getLibraries(); 124 | } 125 | 126 | public File getIntermediaryJar() { 127 | return MINECRAFT_INTERMEDIARY_JAR; 128 | } 129 | 130 | public File getMappedJar() { 131 | return MINECRAFT_MAPPED_JAR; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MinecraftNativesProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.providers; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.util.List; 30 | 31 | import org.zeroturnaround.zip.ZipUtil; 32 | 33 | import org.gradle.api.Project; 34 | 35 | import net.fabricmc.loom.LoomGradleExtension; 36 | import net.fabricmc.loom.util.DownloadUtil; 37 | import net.fabricmc.loom.util.MinecraftVersionInfo.Library; 38 | import net.fabricmc.loom.util.OperatingSystem; 39 | 40 | public class MinecraftNativesProvider { 41 | public static void provide(Project project, LoomGradleExtension extension) throws IOException { 42 | List natives = extension.getDependencyManager().getProvider(MinecraftLibraryProvider.class).natives; 43 | if (natives.isEmpty()) return; //No need to do this 44 | 45 | File nativesDir = extension.getNativesDirectory(); 46 | File jarStore = extension.getNativesJarStore(); 47 | 48 | for (Library library : natives) { 49 | assert library.shouldUse() && library.isNative() && library.hasNativeFor(OperatingSystem.ACTIVE); 50 | String[] parts = library.getArtifactName().split(":", 4); 51 | 52 | File libJarFile = new File(jarStore, parts[0].replace('.', File.separatorChar) + File.separator + parts[1] + File.separator + parts[2] + File.separator + parts[1] + '-' + parts[2] + parts[3] + ".jar"); 53 | DownloadUtil.downloadIfChanged(library.getDownload(OperatingSystem.ACTIVE).url, libJarFile, project.getLogger()); 54 | 55 | //TODO possibly find a way to prevent needing to re-extract after each run, doesnt seem too slow 56 | ZipUtil.unpack(libJarFile, nativesDir); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/MinecraftVersionAdaptable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers; 9 | 10 | import java.io.File; 11 | import java.nio.file.Path; 12 | import java.util.List; 13 | import java.util.Set; 14 | 15 | import org.gradle.api.Project; 16 | 17 | import net.fabricmc.loom.LoomGradleExtension; 18 | import net.fabricmc.loom.LoomGradleExtension.JarMergeOrder; 19 | import net.fabricmc.tinyremapper.TinyRemapper.Builder; 20 | 21 | public interface MinecraftVersionAdaptable { 22 | /** The name of the Minecraft version */ 23 | String getName(); 24 | 25 | /** The {@link JarNamingStrategy naming strategy} for the Minecraft jars */ 26 | default JarNamingStrategy makeNamingStrategy() { 27 | return JarNamingStrategy.forVersion(getName()); 28 | } 29 | 30 | /** The collection of libraries needed to run the jar */ 31 | Set getJavaLibraries(Project project); 32 | 33 | /** The merged jar for the version, will act differently depending on the {@link #getMergeStrategy() merge strategy} */ 34 | Path getMergedJar(); 35 | 36 | /** The way the {@link #getMergedJar() merged jar} was made */ 37 | JarMergeOrder getMergeStrategy(); 38 | 39 | /** The set of namespaces the native Minecraft jars will use (based on the {@link #getMergeStrategy() merge strategy}) */ 40 | default Set getNativeHeaders() { 41 | return getMergeStrategy().getNativeHeaders(); 42 | } 43 | 44 | /** The set of namespaces an Intermediary mapping file should contain for the given {@link #getMergeStrategy() merge strategy} */ 45 | default List getNeededHeaders() { 46 | return getMergeStrategy().getNeededHeaders(); 47 | } 48 | 49 | /** Whether {@link #giveIntermediaries(Path)} needs to be called before {@link #getMergedJar()} can be */ 50 | boolean needsIntermediaries(); 51 | 52 | /** Provide Intermediaries for making the {@link #getMergedJar() merged jar} ({@link #needsIntermediaries() if needed}) */ 53 | void giveIntermediaries(Path mappings); 54 | 55 | /** Gets the Intermediary mappings as given by {@link #giveIntermediaries(Path)} or finds them elsewhere */ 56 | default Path getOrFindIntermediaries(LoomGradleExtension extension) { 57 | return MappingsProvider.getIntermediaries(extension, getName()); 58 | } 59 | 60 | /** Whether to use {@link Builder#ignoreConflicts(boolean)} when remapping the jar */ 61 | default boolean bulldozeMappings(Project project, LoomGradleExtension extension) { 62 | return false; 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/mappings/DummyMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.mappings; 9 | 10 | import java.util.Optional; 11 | import java.util.function.ObjIntConsumer; 12 | 13 | import net.fabricmc.loom.providers.mappings.MappingBlob.Mapping; 14 | import net.fabricmc.loom.util.ThrowingIntObjConsumer; 15 | 16 | class DummyMapping extends Mapping { 17 | private static class DummyField extends Field { 18 | public DummyField(String fromName, String fromDesc) { 19 | super(fromName, fromDesc); 20 | } 21 | 22 | @Override 23 | public String name() { 24 | return null; 25 | } 26 | 27 | @Override 28 | public String nameOr(String alternative) { 29 | return alternative; 30 | } 31 | 32 | @Override 33 | void setMapping(String name, String desc) { 34 | throw new UnsupportedOperationException("Cannot set a name for a dummy field"); 35 | } 36 | 37 | @Override 38 | public Optional comment() { 39 | return Optional.empty(); 40 | } 41 | } 42 | private static class DummyMethod extends Method { 43 | public DummyMethod(String fromName, String fromDesc) { 44 | super(fromName, fromDesc); 45 | } 46 | 47 | @Override 48 | void setMapping(String name, String desc) { 49 | throw new UnsupportedOperationException("Cannot set a name for a dummy method"); 50 | } 51 | 52 | @Override 53 | void addArg(int index, String name) { 54 | throw new UnsupportedOperationException("Cannot add an argument to a dummy method"); 55 | } 56 | 57 | @Override 58 | void addArgComment(int index, String comment) { 59 | throw new UnsupportedOperationException("Cannot add an argument comment to a dummy method"); 60 | } 61 | 62 | @Override 63 | public boolean hasArgs() { 64 | return false; 65 | } 66 | 67 | @Override 68 | public boolean hasArgNames() { 69 | return false; 70 | } 71 | 72 | @Override 73 | public boolean hasArgComments() { 74 | return false; 75 | } 76 | 77 | @Override 78 | Arg[] cloneArgs() { 79 | return new Arg[0]; 80 | } 81 | 82 | @Override 83 | void cloneArgs(Method method) { 84 | throw new UnsupportedOperationException("Cannot add an argument to a dummy method"); 85 | } 86 | 87 | @Override 88 | Arg[] extendArgs(Method that) { 89 | return that.cloneArgs(); 90 | } 91 | 92 | @Override 93 | public String arg(int index) { 94 | return null; 95 | } 96 | 97 | @Override 98 | public Optional argComment(int index) { 99 | return Optional.empty(); 100 | } 101 | 102 | @Override 103 | public void iterateArgs(ThrowingIntObjConsumer argConsumer) { 104 | } 105 | 106 | @Override 107 | public void iterateArgComments(ObjIntConsumer argCommentConsumer) { 108 | } 109 | } 110 | 111 | public DummyMapping(String from) { 112 | super(from); 113 | } 114 | 115 | @Override 116 | public String to() { 117 | return null; 118 | } 119 | 120 | @Override 121 | public String toOr(String alternative) { 122 | return alternative; 123 | } 124 | 125 | @Override 126 | public Optional comment() { 127 | return Optional.empty(); 128 | } 129 | 130 | @Override 131 | public boolean hasMethod(Method other) { 132 | return false; 133 | } 134 | 135 | @Override 136 | Method method(String srcName, String srcDesc) { 137 | return new DummyMethod(srcName, srcDesc); 138 | } 139 | 140 | @Override 141 | public boolean hasField(Field other) { 142 | return false; 143 | } 144 | 145 | @Override 146 | Field field(String srcName, String srcDesc) { 147 | return new DummyField(srcName, srcDesc); 148 | } 149 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/mappings/IMappingAcceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2019 Chocohead 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package net.fabricmc.loom.providers.mappings; 25 | 26 | public interface IMappingAcceptor { 27 | void acceptClass(String srcName, String dstName); 28 | void acceptMethod(String srcClsName, String srcName, String srcDesc, String dstClsName, String dstName, String dstDesc); 29 | void acceptMethodArg(String srcClsName, String srcMethodName, String srcMethodDesc, int lvIndex, String dstArgName); 30 | void acceptField(String srcClsName, String srcName, String srcDesc, String dstClsName, String dstName, String dstDesc); 31 | 32 | void acceptClassComment(String className, String comment); 33 | void acceptMethodComment(String className, String methodName, String desc, String comment); 34 | void acceptMethodArgComment(String className, String methodName, String desc, int lvIndex, String comment); 35 | void acceptFieldComment(String className, String fieldName, String desc, String comment); 36 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/mappings/TinyDuplicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.mappings; 9 | 10 | import java.io.BufferedReader; 11 | import java.io.BufferedWriter; 12 | import java.io.IOException; 13 | import java.nio.file.Files; 14 | import java.nio.file.Path; 15 | import java.util.List; 16 | 17 | public class TinyDuplicator { 18 | public static void duplicateV1Column(Path from, Path to, String copyColumn, String newColumn) throws IOException { 19 | try (BufferedReader reader = TinyReader.getMappingReader(from); BufferedWriter writer = Files.newBufferedWriter(to)) { 20 | readTiny(reader, writer, copyColumn, newColumn); 21 | } 22 | } 23 | 24 | private static void readTiny(BufferedReader reader, BufferedWriter writer, String copyColumn, String newColumn) throws IOException { 25 | List headers = TinyReader.readHeaders(reader); 26 | 27 | int from = headers.indexOf(copyColumn) + 1; 28 | if (from <= 0) throw new IllegalArgumentException("Unable to find column named " + copyColumn); 29 | if (headers.contains(newColumn)) throw new IllegalArgumentException("Column with name " + newColumn + " already exists"); 30 | 31 | writer.write("v1\t"); 32 | for (String header : headers) { 33 | writer.write(header); 34 | writer.write('\t'); 35 | } 36 | writer.write(newColumn); 37 | writer.newLine(); 38 | 39 | for (String line = reader.readLine(); line != null; line = reader.readLine()) { 40 | if (line.isEmpty() || line.startsWith("#")) continue; 41 | 42 | String[] parts = line.split("\t"); 43 | if (parts.length < 2) throw new IOException("Invalid tiny line (missing columns): " + line); 44 | 45 | writer.write(line); 46 | writer.write('\t'); 47 | 48 | switch (parts[0]) { 49 | case "CLASS": 50 | assert parts.length >= 2: "Invalid tiny line (missing columns): " + line; 51 | 52 | writer.write(parts[from]); 53 | break; 54 | 55 | case "METHOD": 56 | case "FIELD": 57 | if (parts.length < 4) throw new IOException("Invalid tiny line (missing columns): " + line); 58 | if (parts[1].isEmpty()) throw new IOException("Invalid tiny line (empty src class): " + line); 59 | if (parts[2].isEmpty()) throw new IOException("Invalid tiny line (empty src method desc): " + line); 60 | 61 | writer.write(parts[2 + from]); 62 | break; 63 | 64 | default: 65 | throw new IOException("Unexpected tiny line (unknown type): " + line); 66 | } 67 | 68 | writer.newLine(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/mappings/TinyWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2019 Chocohead 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package net.fabricmc.loom.providers.mappings; 25 | 26 | import java.io.BufferedWriter; 27 | import java.io.IOException; 28 | import java.io.OutputStreamWriter; 29 | import java.io.UncheckedIOException; 30 | import java.io.Writer; 31 | import java.nio.charset.StandardCharsets; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | import java.util.Arrays; 35 | import java.util.Collection; 36 | import java.util.Collections; 37 | import java.util.HashSet; 38 | import java.util.stream.Collectors; 39 | import java.util.zip.GZIPOutputStream; 40 | 41 | public class TinyWriter implements AutoCloseable { 42 | private final String[] namespaces; 43 | private final Writer writer; 44 | 45 | public TinyWriter(Path file, String... namespaces) throws IOException { 46 | this(file, false, namespaces); 47 | } 48 | 49 | public TinyWriter(Path file, boolean compress, String... namespaces) throws IOException { 50 | Collection uniqueNamespaces = new HashSet<>(); 51 | Collections.addAll(uniqueNamespaces, namespaces); 52 | if (uniqueNamespaces.size() != namespaces.length) { 53 | Collection namespacePool = Arrays.asList(namespaces); 54 | throw new IllegalArgumentException(uniqueNamespaces.stream().filter(namespace -> Collections.frequency(namespacePool, namespace) > 1).collect(Collectors.joining(", ", "Duplicate namespaces: ", ""))); 55 | } 56 | 57 | writer = !compress ? Files.newBufferedWriter(file) : new BufferedWriter(new OutputStreamWriter(new GZIPOutputStream(Files.newOutputStream(file)), StandardCharsets.UTF_8)); 58 | writer.write("v1"); 59 | for (String namespace : this.namespaces = namespaces) { 60 | writer.write('\t'); 61 | writer.write(namespace); 62 | } 63 | writer.write('\n'); 64 | } 65 | 66 | private void ensureComplete(String... names) { 67 | if (names.length < namespaces.length) { 68 | throw new IllegalArgumentException("Missing names for namespaces " + Arrays.asList(namespaces).subList(names.length, namespaces.length)); 69 | } 70 | } 71 | 72 | public void acceptClass(String... names) { 73 | ensureComplete(names); 74 | try { 75 | writer.write("CLASS"); 76 | for (String name : names) { 77 | writer.write('\t'); 78 | if (name != null) writer.write(name); 79 | } 80 | writer.write('\n'); 81 | } catch (IOException e) { 82 | throw new UncheckedIOException("Error writing tiny class", e); 83 | } 84 | } 85 | 86 | public void acceptMethod(String notchClass, String desc, String... names) { 87 | ensureComplete(names); 88 | try { 89 | writer.write("METHOD\t"); 90 | writer.write(notchClass); 91 | writer.write('\t'); 92 | writer.write(desc); 93 | for (String name : names) { 94 | writer.write('\t'); 95 | if (name != null) writer.write(name); 96 | } 97 | writer.write('\n'); 98 | } catch (IOException e) { 99 | throw new UncheckedIOException("Error writing tiny method", e); 100 | } 101 | } 102 | 103 | public void acceptField(String notchClass, String desc, String... names) { 104 | ensureComplete(names); 105 | try { 106 | writer.write("FIELD\t"); 107 | writer.write(notchClass); 108 | writer.write('\t'); 109 | writer.write(desc); 110 | for (String name : names) { 111 | writer.write('\t'); 112 | if (name != null) writer.write(name); 113 | } 114 | writer.write('\n'); 115 | } catch (IOException e) { 116 | throw new UncheckedIOException("Error writing tiny field", e); 117 | } 118 | } 119 | 120 | public void flush() throws IOException { 121 | if (writer != null) writer.flush(); 122 | } 123 | 124 | @Override 125 | public void close() throws IOException { 126 | if (writer != null) writer.close(); 127 | } 128 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/AccessChange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import org.objectweb.asm.Opcodes; 11 | 12 | import com.chocohead.optisine.AccessChange.Access; 13 | 14 | public enum AccessChange { 15 | NONE(null), PRIVATE(Access.PRIVATE), PACKAGE(Access.PACKAGE), PROTECTED(Access.PROTECTED), PUBLIC(Access.PUBLIC); 16 | 17 | private AccessChange(Access access) { 18 | this.access = access; 19 | } 20 | 21 | private final Access access; 22 | public Access toAccess() { 23 | if (access == null) throw new UnsupportedOperationException("Cannot convert AccessChange#" + name() + " to Access!"); 24 | return access; 25 | } 26 | 27 | public static AccessChange forAccess(int original, int access) { 28 | if ((original & ACCESSES) != (access & ACCESSES)) { 29 | if ((original & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) { 30 | return PUBLIC; 31 | } 32 | if ((original & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED) { 33 | return PROTECTED; 34 | } 35 | if ((original & Opcodes.ACC_PRIVATE) == Opcodes.ACC_PRIVATE) { 36 | return PRIVATE; 37 | } 38 | return PACKAGE; 39 | } 40 | 41 | return NONE; 42 | } 43 | 44 | private static final int ACCESSES = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE; 45 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/ChangeSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | public class ChangeSet { 11 | public final AccessChange accessChange; 12 | public final FinalityChange finalityChange; 13 | 14 | public ChangeSet(AccessChange accessChange, FinalityChange finalityChange) { 15 | this.accessChange = accessChange; 16 | this.finalityChange = finalityChange; 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/EmptyMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import java.util.Collection; 11 | import java.util.Collections; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | class EmptyMap implements Map { 16 | @Override 17 | public int size() { 18 | return 0; 19 | } 20 | 21 | @Override 22 | public boolean isEmpty() { 23 | return true; 24 | } 25 | 26 | @Override 27 | public boolean containsKey(Object key) { 28 | return false; 29 | } 30 | 31 | @Override 32 | public boolean containsValue(Object value) { 33 | return false; 34 | } 35 | 36 | @Override 37 | public V get(Object key) { 38 | return null; 39 | } 40 | 41 | @Override 42 | public V put(K key, V value) { 43 | return null; 44 | } 45 | 46 | @Override 47 | public void putAll(Map map) { 48 | } 49 | 50 | @Override 51 | public V remove(Object key) { 52 | return null; 53 | } 54 | 55 | @Override 56 | public void clear() { 57 | } 58 | 59 | @Override 60 | public Set keySet() { 61 | return Collections.emptySet(); 62 | } 63 | 64 | @Override 65 | public Collection values() { 66 | return Collections.emptySet(); 67 | } 68 | 69 | @Override 70 | public Set> entrySet() { 71 | return Collections.emptySet(); 72 | } 73 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/FieldChanges.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Comparator; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.function.Function; 15 | import java.util.stream.Collectors; 16 | 17 | import org.objectweb.asm.tree.FieldNode; 18 | 19 | import com.google.common.collect.Sets; 20 | 21 | public class FieldChanges { 22 | private final List modifiedFields = new ArrayList<>(); 23 | private final List lostFields = new ArrayList<>(); 24 | private final List gainedFields = new ArrayList<>(); 25 | 26 | public FieldChanges(String className, List original, List patched) { 27 | Map originalFields = original.stream().collect(Collectors.toMap(field -> field.name + field.desc, Function.identity())); 28 | Map patchedFields = patched.stream().collect(Collectors.toMap(field -> field.name + field.desc, Function.identity())); 29 | 30 | for (String fieldName : Sets.union(originalFields.keySet(), patchedFields.keySet())) { 31 | FieldNode originalField = originalFields.get(fieldName); 32 | FieldNode patchedField = patchedFields.get(fieldName); 33 | 34 | if (originalField != null) { 35 | if (patchedField != null) {//Both have the field 36 | modifiedFields.add(new FieldComparison(originalField, patchedField)); 37 | } else {//Just the original has the field 38 | lostFields.add(originalField); 39 | } 40 | } else if (patchedField != null) {//Just the modified has the field 41 | gainedFields.add(patchedField); 42 | } else {//Neither have the field?! 43 | throw new IllegalStateException("Unable to find " + fieldName + " in either " + className + " versions"); 44 | } 45 | } 46 | 47 | modifiedFields.sort(Comparator.comparingInt(field -> original.indexOf(field.node))); 48 | lostFields.sort(Comparator.comparingInt(original::indexOf)); 49 | gainedFields.sort(Comparator.comparingInt(patched::indexOf)); 50 | } 51 | 52 | public void annotate(Annotator annotator) { 53 | lostFields.stream().map(field -> field.name + '#' + field.desc).forEach(annotator::dropField); 54 | gainedFields.stream().map(field -> field.name + ";;" + field.desc).forEach(annotator::addField); 55 | modifiedFields.stream().filter(FieldComparison::hasChanged).collect(Collectors.toMap(comparison -> comparison.node.name + ";;" + comparison.node.desc, FieldComparison::toChangeSet)).forEach(annotator::addChangedField); 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/FieldComparison.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import java.util.Objects; 11 | 12 | import org.objectweb.asm.tree.FieldNode; 13 | 14 | public class FieldComparison { 15 | public final FieldNode node; 16 | public final AccessChange access; 17 | public final FinalityChange finality; 18 | 19 | public FieldComparison(FieldNode original, FieldNode patched) { 20 | assert Objects.equals(original.name, patched.name); 21 | assert Objects.equals(original.desc, patched.desc); 22 | node = patched; 23 | 24 | access = AccessChange.forAccess(original.access, patched.access); 25 | finality = FinalityChange.forAccess(original.access, patched.access); 26 | } 27 | 28 | public boolean hasChanged() { 29 | return access != AccessChange.NONE || finality != FinalityChange.NONE; 30 | } 31 | 32 | public ChangeSet toChangeSet() { 33 | return new ChangeSet(access, finality); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/FinalityChange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import org.objectweb.asm.Opcodes; 11 | 12 | import com.chocohead.optisine.FinalityChange.Finality; 13 | 14 | public enum FinalityChange { 15 | NONE(null), GAINED(Finality.GAIN), LOST(Finality.LOST); 16 | 17 | private FinalityChange(Finality finality) { 18 | this.finality = finality; 19 | } 20 | 21 | private final Finality finality; 22 | public Finality toFinality() { 23 | if (finality == null) throw new UnsupportedOperationException("Cannot convert FinalityChange#" + name() + " to Finality!"); 24 | return finality; 25 | } 26 | 27 | public static FinalityChange forAccess(int original, int access) { 28 | if ((original & Opcodes.ACC_FINAL) != (access & Opcodes.ACC_FINAL)) { 29 | return (original & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL ? LOST : GAINED; 30 | } 31 | 32 | return NONE; 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/Lambda.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import java.util.Objects; 11 | 12 | public class Lambda { 13 | public final String owner, name, desc; 14 | public final String method; 15 | 16 | public Lambda(String owner, String name, String desc, String method) { 17 | this.owner = owner; 18 | this.name = name; 19 | this.desc = desc; 20 | this.method = method; 21 | } 22 | 23 | public String getFullName() { 24 | return owner + '#' + name + desc; 25 | } 26 | 27 | public String getName() { 28 | return name.concat(desc); 29 | } 30 | 31 | @Override 32 | public int hashCode() { 33 | return Objects.hash(owner, name, desc, method); 34 | } 35 | 36 | @Override 37 | public boolean equals(Object obj) { 38 | if (this == obj) return true; 39 | if (!(obj instanceof Lambda)) return false; 40 | 41 | Lambda that = (Lambda) obj; 42 | return Objects.equals(owner, that.owner) && Objects.equals(name, that.name) && Objects.equals(desc, that.desc) && Objects.equals(method, that.method); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/providers/openfine/OptiFineVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.providers.openfine; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.util.Enumeration; 13 | import java.util.jar.JarEntry; 14 | import java.util.jar.JarFile; 15 | 16 | import org.gradle.api.InvalidUserDataException; 17 | 18 | import org.objectweb.asm.ClassReader; 19 | import org.objectweb.asm.tree.ClassNode; 20 | import org.objectweb.asm.tree.FieldNode; 21 | 22 | public class OptiFineVersion { 23 | public final String version, minecraftVersion; 24 | public final boolean isInstaller; 25 | 26 | public OptiFineVersion(File file) throws IOException { 27 | ClassNode classNode = new ClassNode(); 28 | boolean isInstaller = false; 29 | try (JarFile jarFile = new JarFile(file)) { 30 | JarEntry entry = jarFile.getJarEntry("net/optifine/Config.class"); 31 | if (entry == null) entry = jarFile.getJarEntry("Config.class"); //Could be an old Optifine version 32 | 33 | if (entry == null) { 34 | throw new InvalidUserDataException("Invalid OptiFine jar, could not find Config"); 35 | } 36 | 37 | ClassReader classReader = new ClassReader(jarFile.getInputStream(entry)); 38 | classReader.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); 39 | 40 | for (Enumeration it = jarFile.entries(); it.hasMoreElements();) { 41 | if (it.nextElement().getName().startsWith("patch/")) { 42 | isInstaller = true; 43 | break; 44 | } 45 | } 46 | } 47 | 48 | String version = null, minecraftVersion = null; 49 | for (FieldNode fieldNode : classNode.fields) { 50 | if ("VERSION".equals(fieldNode.name)) { 51 | version = (String) fieldNode.value; 52 | } else if ("MC_VERSION".equals(fieldNode.name)) { 53 | minecraftVersion = (String) fieldNode.value; 54 | } 55 | } 56 | 57 | if (version == null || version.isEmpty() || minecraftVersion == null || minecraftVersion.isEmpty()) { 58 | throw new IllegalStateException("Unable to find OptiFine version information for " + file + " (only found '" + version + "' for '" + minecraftVersion + "')"); 59 | } 60 | 61 | int split = version.indexOf(minecraftVersion); 62 | if (split < 0 || (split += minecraftVersion.length() + 1) >= version.length()) { 63 | throw new IllegalStateException("Unable to mould the OptiFine version " + version + " (for " + minecraftVersion + ") into shape"); 64 | } 65 | 66 | this.version = version.substring(split); 67 | this.minecraftVersion = minecraftVersion; 68 | this.isInstaller = isInstaller; 69 | } 70 | 71 | public boolean supports(String minecraftVersion) { 72 | return this.minecraftVersion.equals(minecraftVersion); 73 | } 74 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import org.gradle.api.DefaultTask; 28 | import org.gradle.api.tasks.Internal; 29 | 30 | import net.fabricmc.loom.LoomGradleExtension; 31 | 32 | public abstract class AbstractLoomTask extends DefaultTask { 33 | public AbstractLoomTask() { 34 | setGroup("fabric"); 35 | } 36 | 37 | @Internal 38 | protected LoomGradleExtension getExtension() { 39 | return getProject().getExtensions().getByType(LoomGradleExtension.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/AbstractRunTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | import java.nio.file.Files; 29 | import java.nio.file.Path; 30 | import java.util.ArrayList; 31 | import java.util.Arrays; 32 | import java.util.Collections; 33 | import java.util.List; 34 | import java.util.function.Function; 35 | 36 | import org.gradle.api.Project; 37 | import org.gradle.api.tasks.JavaExec; 38 | 39 | import net.fabricmc.loom.LoomGradleExtension; 40 | import net.fabricmc.loom.util.RunConfig; 41 | 42 | public abstract class AbstractRunTask extends JavaExec { 43 | private final Function configProvider; 44 | private RunConfig config; 45 | 46 | public AbstractRunTask(Function config) { 47 | super(); 48 | setGroup("fabric"); 49 | this.configProvider = config; 50 | } 51 | 52 | @Override 53 | public void exec() { 54 | if (config == null) { 55 | config = configProvider.apply(getProject()); 56 | } 57 | 58 | LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); 59 | 60 | List libs = new ArrayList<>(); 61 | 62 | for (File file : getProject().getConfigurations().getByName("runtimeClasspath").getFiles()) { 63 | libs.add(file.getAbsolutePath()); 64 | } 65 | 66 | for (Path file : extension.getUnmappedMods()) { 67 | if (Files.isRegularFile(file)) { 68 | libs.add(file.toFile().getAbsolutePath()); 69 | } 70 | } 71 | 72 | classpath(libs); 73 | List argsSplit = new ArrayList<>(); 74 | String[] args = config.programArgs.split(" "); 75 | int partPos = -1; 76 | 77 | for (int i = 0; i < args.length; i++) { 78 | if (partPos < 0) { 79 | if (args[i].startsWith("\"")) { 80 | if (args[i].endsWith("\"")) { 81 | argsSplit.add(args[i].substring(1, args[i].length() - 1)); 82 | } else { 83 | partPos = i; 84 | } 85 | } else { 86 | argsSplit.add(args[i]); 87 | } 88 | } else if (args[i].endsWith("\"")) { 89 | StringBuilder builder = new StringBuilder(args[partPos].substring(1)); 90 | 91 | for (int j = partPos + 1; j < i; j++) { 92 | builder.append(" ").append(args[j]); 93 | } 94 | 95 | builder.append(" ").append(args[i], 0, args[i].length() - 1); 96 | argsSplit.add(builder.toString()); 97 | partPos = -1; 98 | } 99 | } 100 | 101 | args(argsSplit); 102 | setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); 103 | 104 | super.exec(); 105 | } 106 | 107 | @Override 108 | public void setWorkingDir(File dir) { 109 | if (config == null) { 110 | config = configProvider.apply(getProject()); 111 | } 112 | 113 | if (!dir.exists()) { 114 | dir.mkdirs(); 115 | } 116 | 117 | super.setWorkingDir(dir); 118 | } 119 | 120 | @Override 121 | public String getMain() { 122 | if (config == null) { 123 | config = configProvider.apply(getProject()); 124 | } 125 | 126 | return config.mainClass; 127 | } 128 | 129 | @Override 130 | public List getJvmArgs() { 131 | if (config == null) { 132 | config = configProvider.apply(getProject()); 133 | } 134 | 135 | List superArgs = super.getJvmArgs(); 136 | List args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList()); 137 | args.addAll(Arrays.asList(config.vmArgs.split(" "))); 138 | return args; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/CleanLoomBinaries.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.IOException; 28 | import java.nio.file.Files; 29 | 30 | import org.apache.commons.io.FileUtils; 31 | import org.gradle.api.tasks.TaskAction; 32 | 33 | import net.fabricmc.loom.LoomGradleExtension; 34 | 35 | public class CleanLoomBinaries extends AbstractLoomTask { 36 | @TaskAction 37 | public void run() { 38 | LoomGradleExtension extension = getExtension(); 39 | 40 | extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); 41 | extension.getMinecraftMappedProvider().getMappedJar().delete(); 42 | 43 | try { 44 | Files.delete(extension.getMinecraftProvider().getMergedJar()); 45 | FileUtils.deleteDirectory(extension.getNativesDirectory()); 46 | FileUtils.deleteDirectory(extension.getNativesJarStore()); 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/CleanLoomMappings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.IOException; 28 | import java.nio.file.Files; 29 | 30 | import org.gradle.api.tasks.TaskAction; 31 | 32 | import net.fabricmc.loom.LoomGradleExtension; 33 | import net.fabricmc.loom.util.DeletingFileVisitor; 34 | 35 | public class CleanLoomMappings extends AbstractLoomTask { 36 | @TaskAction 37 | public void run() { 38 | try { 39 | LoomGradleExtension extension = getExtension(); 40 | extension.getMappingsProvider().clearFiles(); 41 | extension.getMinecraftMappedProvider().getIntermediaryJar().delete(); 42 | extension.getMinecraftMappedProvider().getMappedJar().delete(); 43 | Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor()); 44 | } catch (IOException e) { 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/DownloadAssetsTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.IOException; 28 | 29 | import org.gradle.api.Project; 30 | import org.gradle.api.tasks.TaskAction; 31 | 32 | import net.fabricmc.loom.LoomGradleExtension; 33 | import net.fabricmc.loom.providers.MinecraftAssetsProvider; 34 | import net.fabricmc.loom.providers.MinecraftNativesProvider; 35 | 36 | public class DownloadAssetsTask extends AbstractLoomTask { 37 | @TaskAction 38 | public void downloadAssets() throws IOException { 39 | Project project = this.getProject(); 40 | LoomGradleExtension extension = getExtension(); 41 | 42 | MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); 43 | MinecraftNativesProvider.provide(project, extension); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.nio.charset.StandardCharsets; 30 | 31 | import org.apache.commons.io.FileUtils; 32 | import org.gradle.api.tasks.TaskAction; 33 | 34 | import net.fabricmc.loom.util.RunConfig; 35 | 36 | public class GenEclipseRunsTask extends AbstractLoomTask { 37 | @TaskAction 38 | public void genRuns() throws IOException { 39 | File clientRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_client.launch"); 40 | File serverRunConfigs = new File(getProject().getRootDir(), getProject().getName() + "_server.launch"); 41 | 42 | String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); 43 | String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); 44 | 45 | if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { 46 | FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); 47 | } 48 | 49 | if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { 50 | FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); 51 | } 52 | 53 | File runDir = new File(getProject().getRootDir(), getExtension().runDir); 54 | 55 | if (!runDir.exists()) { 56 | runDir.mkdirs(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/GenIdeaProjectTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | 30 | import javax.xml.parsers.DocumentBuilder; 31 | import javax.xml.parsers.DocumentBuilderFactory; 32 | import javax.xml.parsers.ParserConfigurationException; 33 | import javax.xml.transform.OutputKeys; 34 | import javax.xml.transform.Transformer; 35 | import javax.xml.transform.TransformerException; 36 | import javax.xml.transform.TransformerFactory; 37 | import javax.xml.transform.dom.DOMSource; 38 | import javax.xml.transform.stream.StreamResult; 39 | 40 | import org.w3c.dom.Document; 41 | import org.w3c.dom.Element; 42 | import org.w3c.dom.NodeList; 43 | import org.xml.sax.SAXException; 44 | import org.gradle.api.Project; 45 | import org.gradle.api.tasks.TaskAction; 46 | 47 | import net.fabricmc.loom.AbstractPlugin; 48 | import net.fabricmc.loom.LoomGradleExtension; 49 | import net.fabricmc.loom.util.RunConfig; 50 | 51 | public class GenIdeaProjectTask extends AbstractLoomTask { 52 | @TaskAction 53 | public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { 54 | Project project = this.getProject(); 55 | 56 | //Only generate the idea runs on the root project 57 | if (!AbstractPlugin.isRootProject(project)) { 58 | return; 59 | } 60 | 61 | LoomGradleExtension extension = getExtension(); 62 | project.getLogger().lifecycle(":Building idea workspace"); 63 | 64 | File file = project.file(project.getName() + ".iws"); 65 | DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); 66 | DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); 67 | Document doc = docBuilder.parse(file); 68 | 69 | NodeList list = doc.getElementsByTagName("component"); 70 | Element runManager = null; 71 | 72 | for (int i = 0; i < list.getLength(); i++) { 73 | Element element = (Element) list.item(i); 74 | 75 | if (element.getAttribute("name").equals("RunManager")) { 76 | runManager = element; 77 | break; 78 | } 79 | } 80 | 81 | if (runManager == null) { 82 | throw new RuntimeException("Failed to generate intellij run configurations (runManager was not found)"); 83 | } 84 | 85 | runManager.appendChild(RunConfig.clientRunConfig(project).genRuns(runManager)); 86 | runManager.appendChild(RunConfig.serverRunConfig(project).genRuns(runManager)); 87 | 88 | TransformerFactory transformerFactory = TransformerFactory.newInstance(); 89 | Transformer transformer = transformerFactory.newTransformer(); 90 | DOMSource source = new DOMSource(doc); 91 | StreamResult result = new StreamResult(file); 92 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 93 | transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 94 | transformer.transform(source, result); 95 | 96 | File runDir = new File(getProject().getRootDir(), extension.runDir); 97 | 98 | if (!runDir.exists()) { 99 | runDir.mkdirs(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.nio.charset.StandardCharsets; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | import com.google.gson.Gson; 34 | import com.google.gson.GsonBuilder; 35 | import org.apache.commons.io.FileUtils; 36 | import org.gradle.api.Project; 37 | import org.gradle.api.tasks.TaskAction; 38 | 39 | import net.fabricmc.loom.LoomGradleExtension; 40 | import net.fabricmc.loom.util.RunConfig; 41 | 42 | //Recommended vscode plugins: 43 | // https://marketplace.visualstudio.com/items?itemName=redhat.java 44 | // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug 45 | // https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack 46 | public class GenVsCodeProjectTask extends AbstractLoomTask { 47 | @TaskAction 48 | public void genRuns() { 49 | Project project = getProject(); 50 | LoomGradleExtension extension = getExtension(); 51 | File projectDir = project.file(".vscode"); 52 | 53 | if (!projectDir.exists()) { 54 | projectDir.mkdir(); 55 | } 56 | 57 | File launchJson = new File(projectDir, "launch.json"); 58 | 59 | if (launchJson.exists()) { 60 | launchJson.delete(); 61 | } 62 | 63 | VsCodeLaunch launch = new VsCodeLaunch(); 64 | launch.add(RunConfig.clientRunConfig(project)); 65 | launch.add(RunConfig.serverRunConfig(project)); 66 | 67 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 68 | String json = gson.toJson(launch); 69 | 70 | try { 71 | FileUtils.writeStringToFile(launchJson, json, StandardCharsets.UTF_8); 72 | } catch (IOException e) { 73 | throw new RuntimeException("Failed to write launch.json", e); 74 | } 75 | 76 | File runDir = new File(project.getRootDir(), extension.runDir); 77 | 78 | if (!runDir.exists()) { 79 | runDir.mkdirs(); 80 | } 81 | } 82 | 83 | private static class VsCodeLaunch { 84 | public String version = "0.2.0"; 85 | public List configurations = new ArrayList<>(); 86 | 87 | public void add(RunConfig runConfig) { 88 | configurations.add(new VsCodeConfiguration(runConfig)); 89 | } 90 | } 91 | 92 | private static class VsCodeConfiguration { 93 | public String type = "java"; 94 | public String name; 95 | public String request = "launch"; 96 | public String cwd = "${workspaceFolder}/run"; 97 | public String console = "internalConsole"; 98 | public boolean stopOnEntry = false; 99 | public String mainClass; 100 | public String vmArgs; 101 | public String args; 102 | 103 | VsCodeConfiguration(RunConfig runConfig) { 104 | this.name = runConfig.configName; 105 | this.mainClass = runConfig.mainClass; 106 | this.vmArgs = runConfig.vmArgs; 107 | this.args = runConfig.programArgs; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.nio.file.Files; 30 | import java.nio.file.Path; 31 | import java.nio.file.StandardCopyOption; 32 | import java.util.Collection; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.stream.Collectors; 36 | 37 | import javax.inject.Inject; 38 | 39 | import org.gradle.api.file.FileCollection; 40 | import org.gradle.api.tasks.Input; 41 | import org.gradle.api.tasks.InputFile; 42 | import org.gradle.api.tasks.InputFiles; 43 | import org.gradle.api.tasks.Internal; 44 | import org.gradle.api.tasks.OutputFile; 45 | import org.gradle.api.tasks.TaskAction; 46 | 47 | import net.fabricmc.loom.api.decompilers.DecompilationMetadata; 48 | import net.fabricmc.loom.api.decompilers.LoomDecompiler; 49 | import net.fabricmc.loom.util.LineNumberRemapper; 50 | import net.fabricmc.loom.util.progress.ProgressLogger; 51 | 52 | public class GenerateSourcesTask extends AbstractLoomTask { 53 | public final LoomDecompiler decompiler; 54 | private Object input; 55 | private Object output; 56 | private Object lineMap; 57 | private Object libraries; 58 | private final Map decompilerOptions = new HashMap<>(); 59 | private boolean skipForking; 60 | 61 | @Inject 62 | public GenerateSourcesTask(LoomDecompiler decompiler) { 63 | this.decompiler = decompiler; 64 | 65 | setGroup("fabric"); 66 | } 67 | 68 | @InputFile 69 | public File getInput() { 70 | return getProject().file(input); 71 | } 72 | 73 | public void setInput(Object input) { 74 | this.input = input; 75 | } 76 | 77 | @OutputFile 78 | public File getOutput() { 79 | return getProject().file(output); 80 | } 81 | 82 | public void setOutput(Object output) { 83 | this.output = output; 84 | } 85 | 86 | @OutputFile 87 | public File getLineMap() { 88 | return getProject().file(lineMap); 89 | } 90 | 91 | public void setLineMap(Object lineMap) { 92 | this.lineMap = lineMap; 93 | } 94 | 95 | @InputFiles 96 | public FileCollection getLibraries() { 97 | return getProject().files(libraries); 98 | } 99 | 100 | public void setLibraries(Object libraries) { 101 | this.libraries = libraries; 102 | } 103 | 104 | @Input 105 | public Map getDecompilerOptions() { 106 | return decompilerOptions; 107 | } 108 | 109 | public void decompilerOption(String name, Object value) { 110 | decompilerOptions.put(name, value); 111 | } 112 | 113 | @Internal 114 | public boolean isSkipForking() { 115 | return skipForking; 116 | } 117 | 118 | public void setSkipForking(boolean skipForking) { 119 | this.skipForking = skipForking; 120 | } 121 | 122 | @TaskAction 123 | public void doTask() throws Throwable { 124 | Path javaDocs = getExtension().getMappingsProvider().getDecompileMappings().toAbsolutePath(); 125 | Collection libraries = getLibraries().getFiles().stream().map(File::toPath).collect(Collectors.toSet()); 126 | DecompilationMetadata metadata = new DecompilationMetadata(getDecompilerOptions(), !isSkipForking(), javaDocs, libraries); 127 | 128 | Path compiledJar = getInput().toPath(); 129 | assert Files.exists(compiledJar); 130 | Path sourcesDestination = getOutput().toPath(); 131 | Files.deleteIfExists(sourcesDestination); 132 | Path linemap = getLineMap().toPath(); 133 | Files.deleteIfExists(linemap); 134 | 135 | decompiler.decompile(compiledJar, sourcesDestination, linemap, metadata); 136 | 137 | if (Files.exists(linemap)) { 138 | Path lineMapped = new File(getTemporaryDir(), "line-mapped.jar").toPath(); 139 | Files.deleteIfExists(lineMapped); //Just to make sure 140 | 141 | remapLineNumbers(compiledJar, linemap, lineMapped); 142 | 143 | Files.move(lineMapped, compiledJar, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); 144 | } else { 145 | getLogger().info("Skipping line mapping as " + linemap + " doesn't exist"); 146 | } 147 | } 148 | 149 | private void remapLineNumbers(Path oldCompiledJar, Path linemap, Path linemappedJarDestination) throws IOException { 150 | getLogger().info(":adjusting line numbers"); 151 | LineNumberRemapper remapper = new LineNumberRemapper(); 152 | remapper.readMappings(linemap.toFile()); 153 | 154 | ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName()); 155 | progressLogger.start("Adjusting line numbers", "linemap"); 156 | 157 | remapper.process(progressLogger, oldCompiledJar.toFile(), linemappedJarDestination.toFile()); 158 | 159 | progressLogger.completed(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import java.io.File; 28 | 29 | import org.gradle.api.tasks.Input; 30 | import org.gradle.api.tasks.InputFile; 31 | import org.gradle.api.tasks.OutputFile; 32 | import org.gradle.api.tasks.TaskAction; 33 | 34 | import net.fabricmc.loom.util.SourceRemapper; 35 | 36 | public class RemapSourcesJarTask extends AbstractLoomTask { 37 | private Object input; 38 | private Object output; 39 | private String direction = "intermediary"; 40 | 41 | @TaskAction 42 | public void remap() throws Exception { 43 | SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); 44 | } 45 | 46 | @InputFile 47 | public File getInput() { 48 | return getProject().file(input); 49 | } 50 | 51 | @OutputFile 52 | public File getOutput() { 53 | return getProject().file(output == null ? input : output); 54 | } 55 | 56 | @Input 57 | public String getTargetNamespace() { 58 | return direction; 59 | } 60 | 61 | public void setInput(Object input) { 62 | this.input = input; 63 | } 64 | 65 | public void setOutput(Object output) { 66 | this.output = output; 67 | } 68 | 69 | public void setTargetNamespace(String value) { 70 | this.direction = value; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/RemappingJar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2019 Chocohead 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package net.fabricmc.loom.task; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.nio.file.Files; 29 | import java.nio.file.Path; 30 | import java.nio.file.StandardCopyOption; 31 | 32 | import org.apache.commons.io.FilenameUtils; 33 | 34 | import org.gradle.api.tasks.Input; 35 | import org.gradle.api.tasks.OutputFile; 36 | import org.gradle.api.tasks.bundling.Jar; 37 | import groovy.lang.Closure; 38 | 39 | import net.fabricmc.loom.LoomGradleExtension; 40 | import net.fabricmc.loom.util.AccessTransformerHelper; 41 | 42 | public class RemappingJar extends Jar { 43 | public File destination; 44 | public boolean nestJar = true; 45 | public boolean includeAT = true; 46 | public boolean convertAT; 47 | 48 | public RemappingJar() { 49 | setGroup("fabric"); 50 | 51 | configure(new Closure(this, this) { 52 | private static final long serialVersionUID = -5294178679681444341L; 53 | 54 | @Override 55 | public RemappingJar call() { 56 | AccessTransformerHelper.copyInAT(getProject().getExtensions().getByType(LoomGradleExtension.class), RemappingJar.this); 57 | return null; 58 | } 59 | }); 60 | doLast(task -> { 61 | try { 62 | Path input = getUnmappedJar().toPath(); 63 | Files.move(getArchivePath().toPath(), input, StandardCopyOption.REPLACE_EXISTING); 64 | 65 | RemapJarTask.remap(task, input, getArchivePath().toPath(), nestJar, !includeAT, convertAT); 66 | getProject().getExtensions().getByType(LoomGradleExtension.class).addUnmappedMod(input); 67 | } catch (IOException e) { 68 | throw new RuntimeException("Failed to remap jar", e); 69 | } 70 | }); 71 | } 72 | 73 | @Input 74 | public boolean isNestJar() { 75 | return nestJar; 76 | } 77 | 78 | @Input 79 | public boolean isIncludeAT() { 80 | return includeAT; 81 | } 82 | 83 | @Input 84 | public boolean isConvertAT() { 85 | return convertAT; 86 | } 87 | 88 | @OutputFile 89 | public File getUnmappedJar() { 90 | if (destination == null) { 91 | String s = getArchivePath().getAbsolutePath(); 92 | return new File(FilenameUtils.removeExtension(s) + "-dev.jar"); 93 | } 94 | 95 | return destination; 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/RunClientTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import net.fabricmc.loom.util.RunConfig; 28 | 29 | public class RunClientTask extends AbstractRunTask { 30 | public RunClientTask() { 31 | super(RunConfig::clientRunConfig); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/task/RunServerTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.task; 26 | 27 | import net.fabricmc.loom.util.RunConfig; 28 | 29 | public class RunServerTask extends AbstractRunTask { 30 | public RunServerTask() { 31 | super(RunConfig::serverRunConfig); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/Checksum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | 30 | import com.google.common.hash.Hashing; 31 | import com.google.common.io.Files; 32 | 33 | import org.gradle.api.logging.Logger; 34 | import org.gradle.api.logging.Logging; 35 | 36 | public class Checksum { 37 | private static final Logger log = Logging.getLogger(Checksum.class); 38 | 39 | public static boolean equals(File file, String checksum) { 40 | if (file == null) { 41 | return false; 42 | } 43 | 44 | try { 45 | @SuppressWarnings("deprecation") 46 | String hash = Files.asByteSource(file).hash(Hashing.sha1()).toString(); 47 | 48 | log.debug("Checksum check: '" + hash + "' == '" + checksum + "'?"); 49 | return hash.equals(checksum); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/Closer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util; 9 | 10 | import java.util.ArrayDeque; 11 | import java.util.Queue; 12 | import java.util.Stack; 13 | 14 | /** Like {@link com.google.common.io.Closer Guava's Closer} but closes the resources as a {@link Queue} rather than as a {@link Stack} */ 15 | public final class Closer implements AutoCloseable { 16 | private final Queue resources; 17 | 18 | public static Closer create() { 19 | return new Closer(); 20 | } 21 | 22 | public static Closer create(int expectedSize) { 23 | return new Closer(expectedSize); 24 | } 25 | 26 | private Closer() { 27 | resources = new ArrayDeque<>(); 28 | } 29 | 30 | private Closer(int expectedSize) { 31 | resources = new ArrayDeque<>(expectedSize); 32 | } 33 | 34 | public C register(C closeable) { 35 | if (closeable != null) { 36 | resources.add(closeable); 37 | } 38 | 39 | return closeable; 40 | } 41 | 42 | @Override 43 | public void close() throws Exception { 44 | Exception thrown = null; 45 | 46 | while (!resources.isEmpty()) { 47 | try { 48 | resources.remove().close(); 49 | } catch (Exception e) { 50 | if (thrown == null) { 51 | thrown = e; 52 | } else { 53 | thrown.addSuppressed(e); 54 | } 55 | } 56 | } 57 | 58 | if (thrown != null) throw thrown; 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.util.List; 28 | 29 | import com.google.common.collect.ImmutableList; 30 | 31 | import net.fabricmc.loom.dependencies.RemappedConfigurationEntry; 32 | 33 | public class Constants { 34 | public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker"; 35 | public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker"; 36 | 37 | public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/"; 38 | public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/"; 39 | 40 | public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32"; 41 | 42 | public static final String MOD_COMPILE_CLASSPATH = "modCompileClasspath"; 43 | public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped"; 44 | public static final RemappedConfigurationEntry MOD_COMPILE, MOD_API, MOD_IMPLEMENTATION, MOD_RUNTIME, MOD_COMPILE_ONLY; 45 | public static final List MOD_COMPILE_ENTRIES = ImmutableList.of( 46 | MOD_COMPILE = new RemappedConfigurationEntry("modCompile", "compile", true, "compile"), 47 | MOD_API = new RemappedConfigurationEntry("modApi", "api", true, "compile"), 48 | MOD_IMPLEMENTATION = new RemappedConfigurationEntry("modImplementation", "implementation", true, "runtime"), 49 | MOD_RUNTIME = new RemappedConfigurationEntry("modRuntime", "runtimeOnly", false, ""), 50 | MOD_COMPILE_ONLY = new RemappedConfigurationEntry("modCompileOnly", "compileOnly", true, "") 51 | ); 52 | 53 | public static final String INCLUDE = "include"; 54 | public static final String MINECRAFT = "minecraft"; 55 | public static final String MINECRAFT_LIBRARIES = "minecraftInducedLibraries"; 56 | public static final String MINECRAFT_DEPENDENCIES = "minecraftLibraries"; 57 | public static final String MINECRAFT_INTERMEDIARY = "minecraftIntermediary"; 58 | public static final String MINECRAFT_NAMED = "minecraftNamed"; 59 | public static final String MINECRAFT_LINEMAPPED = "minecraftLinemapped"; 60 | public static final String MAPPINGS_RAW = "mappings"; 61 | public static final String MAPPINGS = "mappingsNative"; 62 | 63 | public static final String MIXIN_COMPILE_EXTENSIONS_VERSION = "0.4.6"; 64 | public static final String DEV_LAUNCH_INJECTOR_VERSION = "0.2.1+build.8"; 65 | public static final String TERMINAL_CONSOLE_APPENDER_VERSION = "1.2.0"; 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/ConsumingOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.IOException; 28 | import java.io.OutputStream; 29 | import java.util.function.Consumer; 30 | 31 | /** 32 | * Created by covers1624 on 20/12/18. 33 | */ 34 | public class ConsumingOutputStream extends OutputStream { 35 | private final Consumer consumer; 36 | 37 | private StringBuilder buffer = new StringBuilder(); 38 | 39 | public ConsumingOutputStream(Consumer consumer) { 40 | this.consumer = consumer; 41 | } 42 | 43 | @Override 44 | public void write(int b) throws IOException { 45 | char ch = (char) (b & 0xFF); 46 | buffer.append(ch); 47 | 48 | if (ch == '\n' || ch == '\r') { 49 | flush(); 50 | } 51 | } 52 | 53 | @Override 54 | public void flush() throws IOException { 55 | String str = buffer.toString(); 56 | 57 | if (str.endsWith("\r") || str.endsWith("\n")) { 58 | str = str.trim(); 59 | 60 | if (!str.isEmpty()) { 61 | consumer.accept(str); 62 | } 63 | 64 | buffer = new StringBuilder(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/DeletingFileVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.IOException; 28 | import java.nio.file.FileVisitResult; 29 | import java.nio.file.Files; 30 | import java.nio.file.Path; 31 | import java.nio.file.SimpleFileVisitor; 32 | import java.nio.file.attribute.BasicFileAttributes; 33 | 34 | public class DeletingFileVisitor extends SimpleFileVisitor { 35 | @Override 36 | public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException { 37 | Files.delete(path); 38 | return FileVisitResult.CONTINUE; 39 | } 40 | 41 | @Override 42 | public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException { 43 | Files.delete(path); 44 | return FileVisitResult.CONTINUE; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/GradleSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.lang.reflect.Method; 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | import org.gradle.api.Project; 32 | import org.gradle.api.artifacts.repositories.ArtifactRepository; 33 | import org.gradle.api.file.ProjectLayout; 34 | import org.gradle.api.file.RegularFileProperty; 35 | 36 | /** This is used to bridge the gap over large Gradle API changes. */ 37 | public class GradleSupport { 38 | //Based on https://github.com/gradle/gradle/blob/master/subprojects/base-services/src/main/java/org/gradle/util/GradleVersion.java#L37 39 | private static final Pattern VERSION_MATCHER = Pattern.compile("^(\\d+)\\.(\\d+)(?:\\.(\\d+)(?:\\.\\d+)*)?(?:-.+)?$"); 40 | 41 | public static int majorGradleVersion(Project project) { 42 | String version = project.getGradle().getGradleVersion(); 43 | 44 | Matcher matcher = VERSION_MATCHER.matcher(version); 45 | if (!matcher.matches()) throw new IllegalArgumentException("Weird Gradle version: " + version); 46 | 47 | return Integer.parseUnsignedInt(matcher.group(1)); 48 | } 49 | 50 | public static int minorGradleVersion(Project project) { 51 | String version = project.getGradle().getGradleVersion(); 52 | 53 | Matcher matcher = VERSION_MATCHER.matcher(version); 54 | if (!matcher.matches()) throw new IllegalArgumentException("Weird Gradle version: " + version); 55 | 56 | return Integer.parseUnsignedInt(matcher.group(2)); 57 | } 58 | 59 | public static int patchGradleVersion(Project project) { 60 | String version = project.getGradle().getGradleVersion(); 61 | 62 | Matcher matcher = VERSION_MATCHER.matcher(version); 63 | if (!matcher.matches()) throw new IllegalArgumentException("Weird Gradle version: " + version); 64 | 65 | //Nothing says Gradle must have a patch version 66 | return matcher.group(3) != null ? Integer.parseUnsignedInt(matcher.group(3)) : 0; 67 | } 68 | 69 | public static RegularFileProperty getFileProperty(Project project) { 70 | try { 71 | return project.getObjects().fileProperty(); 72 | } catch (NoSuchMethodError e) { 73 | assert majorGradleVersion(project) < 5; 74 | } 75 | 76 | try { 77 | Method method = ProjectLayout.class.getMethod("fileProperty"); 78 | assert method.isAccessible(); 79 | return (RegularFileProperty) method.invoke(project.getLayout()); 80 | } catch (ReflectiveOperationException | ClassCastException e) { 81 | throw new IllegalStateException("Can't find new or old fileProperty?", e); 82 | } 83 | } 84 | 85 | public static void onlyForGroupMatching(Project project, ArtifactRepository repo, String regex) { 86 | if (majorGradleVersion(project) >= 6 || majorGradleVersion(project) == 5 && minorGradleVersion(project) >= 1) { 87 | repo.content(filter -> { 88 | filter.includeGroupByRegex(regex); 89 | }); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.util.Optional; 28 | import java.util.stream.Stream; 29 | 30 | import groovy.util.Node; 31 | import groovy.xml.QName; 32 | 33 | public final class GroovyXmlUtil { 34 | private GroovyXmlUtil() { } 35 | 36 | public static Node getOrCreateNode(Node parent, String name) { 37 | return getNode(parent, name).orElseGet(() -> parent.appendNode(name)); 38 | } 39 | 40 | public static Optional getNode(Node parent, String name) { 41 | return getNodes(parent, name).findFirst(); 42 | } 43 | 44 | public static Stream getNodes(Node parent, String name) { 45 | return childrenNodesStream(parent).filter(node -> { 46 | Object nodeName = node.name(); 47 | if (nodeName == null) return name == null; //Probably shouldn't be null but... 48 | 49 | if (nodeName instanceof CharSequence) { 50 | return name.contentEquals((CharSequence) nodeName); 51 | } 52 | 53 | if (nodeName instanceof QName) { 54 | return ((QName) nodeName).matches(name); 55 | } 56 | 57 | throw new UnsupportedOperationException("Cannot determine if " + nodeName.getClass() + " is the same as a String"); 58 | }); 59 | } 60 | 61 | private static Stream childrenNodesStream(Node node) { 62 | return fishForNodes(node.children().stream()); 63 | } 64 | 65 | /** 66 | * Type safe casting a raw type {@link Stream} to a {@code Stream} 67 | * 68 | * @param stuff A raw stream of objects, potentially containing {@link Node}s 69 | * 70 | * @return The given raw stream with a filter and mapping operation on return only Nodes 71 | */ 72 | private static Stream fishForNodes(Stream stuff) { 73 | return stuff.filter(o -> o instanceof Node).map(Node.class::cast); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/HexaFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util; 9 | 10 | import java.util.Objects; 11 | import java.util.function.BiFunction; 12 | import java.util.function.Function; 13 | 14 | /** 15 | * Represents a function that accepts six arguments and produces a result. 16 | * This is the six-arity specialisation of {@link Function}. 17 | * 18 | *

This is a functional interface whose functional method is 19 | * {@link #apply(Object, Object, Object, Object, Object, Object)}. 20 | * 21 | * @param the type of the first argument to the function 22 | * @param the type of the second argument to the function 23 | * @param the type of the third argument to the function 24 | * @param the type of the fourth argument to the function 25 | * @param the type of the fifth argument to the function 26 | * @param the type of the fifth argument to the function 27 | * @param the type of the result of the function 28 | * 29 | * @see Function 30 | * @see BiFunction 31 | */ 32 | @FunctionalInterface 33 | public interface HexaFunction { 34 | /** 35 | * Applies this function to the given arguments. 36 | * 37 | * @param t The first function argument 38 | * @param u The second function argument 39 | * @param v The third function argument 40 | * @param w The fourth function argument 41 | * @param x The fifth function argument 42 | * @param y The sixth function argument 43 | * @return the function result 44 | */ 45 | R apply(T t, U u, V v, W w, X x, Y y); 46 | 47 | /** 48 | * Returns a composed function that first applies this function to its input, 49 | * and then applies the {@code after} function to the result. If evaluation of 50 | * either function throws an exception, it is relayed to the caller of the 51 | * composed function. 52 | * 53 | * @param The type of output of the {@code after} function, and of the 54 | * composed function 55 | * @param after The function to apply after this function is applied 56 | * 57 | * @return A composed function that first applies this function and then applies 58 | * the {@code after} function 59 | * 60 | * @throws NullPointerException If after is null 61 | */ 62 | default HexaFunction andThen(Function after) { 63 | Objects.requireNonNull(after); 64 | return (t, u, v, w, x, y) -> after.apply(apply(t, u, v, w, x, y)); 65 | } 66 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/LineNumberRemapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import static java.text.MessageFormat.format; 28 | 29 | import java.io.BufferedReader; 30 | import java.io.File; 31 | import java.io.FileReader; 32 | import java.io.IOException; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.zip.ZipEntry; 36 | 37 | import org.objectweb.asm.ClassReader; 38 | import org.objectweb.asm.ClassVisitor; 39 | import org.objectweb.asm.ClassWriter; 40 | import org.objectweb.asm.Label; 41 | import org.objectweb.asm.MethodVisitor; 42 | import org.objectweb.asm.Opcodes; 43 | 44 | import org.zeroturnaround.zip.ZipUtil; 45 | import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer; 46 | import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; 47 | 48 | import net.fabricmc.loom.util.progress.ProgressLogger; 49 | 50 | /** 51 | * TODO, Move to stitch. 52 | * Created by covers1624 on 18/02/19. 53 | */ 54 | public class LineNumberRemapper { 55 | private final Map lineMap = new HashMap<>(); 56 | 57 | public void readMappings(File lineMappings) { 58 | try (BufferedReader reader = new BufferedReader(new FileReader(lineMappings))) { 59 | RClass clazz = null; 60 | String line = null; 61 | int i = 0; 62 | 63 | try { 64 | while ((line = reader.readLine()) != null) { 65 | if (line.isEmpty()) { 66 | continue; 67 | } 68 | 69 | String[] segs = line.trim().split("\t"); 70 | 71 | if (line.charAt(0) != '\t') { 72 | clazz = lineMap.computeIfAbsent(segs[0], RClass::new); 73 | clazz.maxLine = Integer.parseInt(segs[1]); 74 | clazz.maxLineDest = Integer.parseInt(segs[2]); 75 | } else { 76 | clazz.lineMap.put(Integer.parseInt(segs[0]), Integer.parseInt(segs[1])); 77 | } 78 | 79 | i++; 80 | } 81 | } catch (Exception e) { 82 | throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", i, line), e); 83 | } 84 | } catch (IOException e) { 85 | throw new RuntimeException("Exception reading LineMappings file.", e); 86 | } 87 | } 88 | 89 | public void process(ProgressLogger logger, File from, File to) { 90 | ZipEntryTransformerEntry[] transformers = lineMap.entrySet().stream().map(entry -> { 91 | String className = entry.getKey(); 92 | 93 | return new ZipEntryTransformerEntry(className + ".class", new ByteArrayZipEntryTransformer() { 94 | private final RClass rClass = entry.getValue(); 95 | 96 | @Override 97 | protected byte[] transform(ZipEntry zipEntry, byte[] input) throws IOException { 98 | if (logger != null) logger.progress("Remapping " + className); 99 | 100 | ClassReader reader = new ClassReader(input); 101 | ClassWriter writer = new ClassWriter(reader, 0); 102 | 103 | reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, rClass), 0); 104 | return writer.toByteArray(); 105 | } 106 | 107 | @Override 108 | protected boolean preserveTimestamps() { 109 | return true; //Why not? 110 | } 111 | }); 112 | }).toArray(ZipEntryTransformerEntry[]::new); 113 | 114 | ZipUtil.transformEntries(from, transformers, to); 115 | } 116 | 117 | private static class LineNumberVisitor extends ClassVisitor { 118 | private final RClass rClass; 119 | 120 | LineNumberVisitor(int api, ClassVisitor classVisitor, RClass rClass) { 121 | super(api, classVisitor); 122 | this.rClass = rClass; 123 | } 124 | 125 | @Override 126 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 127 | return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) { 128 | @Override 129 | public void visitLineNumber(int line, Label start) { 130 | int tLine = line; 131 | 132 | if (tLine <= 0) { 133 | super.visitLineNumber(line, start); 134 | } else if (tLine >= rClass.maxLine) { 135 | super.visitLineNumber(rClass.maxLineDest, start); 136 | } else { 137 | Integer matchedLine = null; 138 | 139 | while (tLine <= rClass.maxLine && (matchedLine = rClass.lineMap.get(tLine)) == null) { 140 | tLine++; 141 | } 142 | 143 | super.visitLineNumber(matchedLine != null ? matchedLine : rClass.maxLineDest, start); 144 | } 145 | } 146 | }; 147 | } 148 | } 149 | 150 | private static class RClass { 151 | @SuppressWarnings("unused") 152 | private final String name; 153 | private int maxLine; 154 | private int maxLineDest; 155 | private final Map lineMap = new HashMap<>(); 156 | 157 | private RClass(String name) { 158 | this.name = name; 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/ManifestVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public class ManifestVersion { 31 | public List versions = new ArrayList<>(); 32 | 33 | public static class Versions { 34 | public String id, url; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/MinecraftVersionInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2021 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util; 9 | 10 | import java.net.URL; 11 | import java.util.Collections; 12 | import java.util.Date; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.regex.Pattern; 16 | 17 | import com.google.common.collect.ObjectArrays; 18 | import com.google.gson.annotations.SerializedName; 19 | 20 | import net.fabricmc.loom.util.MinecraftVersionInfo.Library.Rule.Action; 21 | 22 | public class MinecraftVersionInfo { 23 | public static class Library { 24 | public static class Rule { 25 | public enum Action { 26 | @SerializedName("allow") 27 | ALLOW, 28 | @SerializedName("disallow") 29 | DISALLOW; 30 | } 31 | 32 | public static class OS { 33 | public OperatingSystem name; 34 | public String version; 35 | public String arch; 36 | 37 | public boolean doesMatch(OperatingSystem os) { 38 | if (name != null && name != os) { 39 | return false; 40 | } 41 | 42 | if (version != null && !Pattern.matches(version, System.getProperty("os.version"))) { 43 | return false; 44 | } 45 | 46 | if (arch != null && !Pattern.matches(arch, System.getProperty("os.arch"))) { 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | } 53 | 54 | public Action action = Action.ALLOW; 55 | public OS os; 56 | 57 | public boolean doesRuleApply(OperatingSystem with) { 58 | return os == null || os.doesMatch(with); 59 | } 60 | } 61 | 62 | public static class Extraction { 63 | public List exclude = Collections.emptyList(); 64 | 65 | public boolean isSpecial() { 66 | return !exclude.isEmpty(); 67 | } 68 | } 69 | 70 | public static class Downloads { 71 | public Download artifact; 72 | public Map classifiers = Collections.emptyMap(); 73 | 74 | public boolean isSpecial() { 75 | return !classifiers.isEmpty(); 76 | } 77 | 78 | public Download getDownload(String classifier) { 79 | return classifier == null ? artifact : classifiers.get(classifier); 80 | } 81 | } 82 | 83 | public String name; 84 | public Rule[] rules; 85 | public Map natives; 86 | public Extraction extract; 87 | public Downloads downloads; 88 | 89 | public boolean shouldUse() { 90 | return shouldUse(OperatingSystem.ACTIVE); 91 | } 92 | 93 | public boolean shouldUse(OperatingSystem os) { 94 | if (rules == null || rules.length == 0) return true; 95 | 96 | for (int i = rules.length - 1; i >= 0; i--) { 97 | if (rules[i].doesRuleApply(os)) { 98 | return rules[i].action == Action.ALLOW; 99 | } 100 | } 101 | 102 | return false; 103 | } 104 | 105 | public boolean willUse() { 106 | return willUse(OperatingSystem.ACTIVE); 107 | } 108 | 109 | public boolean willUse(OperatingSystem os) { 110 | return shouldUse(os) && (!isNative() || hasNativeFor(os)); 111 | } 112 | 113 | public String getArtifactName() { 114 | return getArtifactName(OperatingSystem.ACTIVE); 115 | } 116 | 117 | public String getArtifactName(OperatingSystem os) { 118 | if (!isNative()) return name; 119 | 120 | if (os == null || !hasNativeFor(os)) { 121 | throw new IllegalArgumentException(name + " has no native for " + os); 122 | } 123 | 124 | return name + ':' + natives.get(os); 125 | } 126 | 127 | public boolean isNative() { 128 | return natives != null; 129 | } 130 | 131 | public boolean hasNativeFor(OperatingSystem os) { 132 | return isNative() && natives.containsKey(os); 133 | } 134 | 135 | public Download getDownload() { 136 | return downloads.getDownload(null); 137 | } 138 | 139 | public Download getDownload(OperatingSystem os) { 140 | if (os == null || !hasNativeFor(os) || !downloads.isSpecial()) { 141 | throw new IllegalArgumentException(name + " has no native for " + os); 142 | } 143 | 144 | return downloads.getDownload(natives.get(os)); 145 | } 146 | } 147 | 148 | public static class Download { 149 | public URL url; 150 | public URL[] altUrls = new URL[0]; 151 | @SerializedName("sha1") 152 | public String hash; 153 | public int size; 154 | 155 | public URL[] getURLs() { 156 | return ObjectArrays.concat(url, altUrls); 157 | } 158 | } 159 | 160 | public static class AssetIndex { 161 | public String id; 162 | public URL url; 163 | @SerializedName("sha1") 164 | public String hash; 165 | 166 | public String getFabricId(String version) { 167 | return id.equals(version) ? version : version + '-' + id; 168 | } 169 | } 170 | 171 | public String id; 172 | public Date releaseTime; 173 | public List libraries; 174 | public Map downloads; 175 | public AssetIndex assetIndex; 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/MixinRefmapHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.util.HashSet; 31 | import java.util.Set; 32 | import java.util.zip.ZipEntry; 33 | 34 | import com.google.gson.Gson; 35 | import com.google.gson.GsonBuilder; 36 | import com.google.gson.JsonObject; 37 | import com.google.gson.JsonSyntaxException; 38 | import com.google.gson.stream.JsonReader; 39 | import com.google.gson.stream.JsonToken; 40 | 41 | import org.zeroturnaround.zip.ZipUtil; 42 | import org.zeroturnaround.zip.transform.StringZipEntryTransformer; 43 | import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; 44 | 45 | public final class MixinRefmapHelper { 46 | private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); 47 | 48 | private MixinRefmapHelper() { } 49 | 50 | public static boolean addRefmapName(String filename, String mixinVersion, File output) { 51 | Set mixinFilenames = findMixins(output); 52 | 53 | if (mixinFilenames.size() > 0) { 54 | return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { 55 | @Override 56 | protected String transform(ZipEntry zipEntry, String input) throws IOException { 57 | try { 58 | JsonObject json = GSON.fromJson(input, JsonObject.class); 59 | 60 | if (!json.has("refmap")) { 61 | json.addProperty("refmap", filename); 62 | } 63 | 64 | if (!json.has("minVersion") && mixinVersion != null) { 65 | json.addProperty("minVersion", mixinVersion); 66 | } 67 | 68 | return GSON.toJson(json); 69 | } catch (JsonSyntaxException e) { 70 | System.err.println("Suspected Mixin config " + zipEntry + " is not a JSON object"); 71 | e.printStackTrace(); 72 | return input; 73 | } 74 | } 75 | })).toArray(ZipEntryTransformerEntry[]::new)); 76 | } else { 77 | return false; 78 | } 79 | } 80 | 81 | private static Set findMixins(File output) { 82 | // first, identify all of the mixin files 83 | Set mixinFilename = new HashSet<>(); 84 | // TODO: this is a lovely hack 85 | ZipUtil.iterate(output, (stream, entry) -> { 86 | if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { 87 | // JSON file in root directory 88 | try (JsonReader in = new JsonReader(new InputStreamReader(stream))) { 89 | out: if (in.peek() == JsonToken.BEGIN_OBJECT) { 90 | boolean hasPackage = false; 91 | boolean probablyMixin = false; 92 | boolean hasRefmap = false; 93 | boolean hasMinVersion = false; 94 | 95 | in.beginObject(); 96 | while (in.hasNext()) { 97 | switch (in.nextName()) { 98 | case "package": 99 | if (in.peek() == JsonToken.STRING) { 100 | hasPackage = true; 101 | } else { 102 | break out; //Not Mixin 103 | } 104 | break; 105 | 106 | case "mixins": 107 | case "client": 108 | case "server": 109 | if (in.peek() == JsonToken.BEGIN_ARRAY) { 110 | probablyMixin = true; 111 | } else { 112 | break out; //Not Mixin 113 | } 114 | break; 115 | 116 | case "refmap": 117 | if (in.peek() == JsonToken.STRING) { 118 | hasRefmap = true; 119 | } else { 120 | break out; //Not Mixin 121 | } 122 | break; 123 | 124 | case "minVersion": 125 | if (in.peek() == JsonToken.STRING || in.peek() == JsonToken.NUMBER) { 126 | hasMinVersion = true; 127 | } else { 128 | break out; //Not Mixin 129 | } 130 | break; 131 | } 132 | 133 | in.skipValue(); //Don't actually mind what the value is 134 | } 135 | 136 | if (hasPackage && probablyMixin && (!hasRefmap || !hasMinVersion)) { 137 | mixinFilename.add(entry.getName()); 138 | } 139 | } 140 | } catch (IOException | IllegalStateException e) { 141 | System.err.println("Error reading " + entry); 142 | e.printStackTrace(); 143 | } 144 | } 145 | }); 146 | return mixinFilename; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/OperatingSystem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2021 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util; 9 | 10 | import java.util.Locale; 11 | 12 | import com.google.gson.annotations.SerializedName; 13 | 14 | public enum OperatingSystem { 15 | @SerializedName(value = "windows", alternate = "win") 16 | WINDOWS("win"), 17 | @SerializedName(value = "osx", alternate = "mac") 18 | OSX("mac"), 19 | @SerializedName(value = "linux", alternate = "unix") 20 | LINUX("linux", "unix"); 21 | public static final transient OperatingSystem ACTIVE = get(); 22 | 23 | private final String[] names; 24 | 25 | private OperatingSystem(String... names) { 26 | this.names = names; 27 | } 28 | 29 | private static OperatingSystem get() { 30 | String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); 31 | 32 | for (OperatingSystem os : values()) { 33 | for (String name : os.names) { 34 | if (osName.contains(name)) { 35 | return os; 36 | } 37 | } 38 | } 39 | 40 | throw new IllegalStateException("Unable to find OS for current system: " + osName); 41 | } 42 | 43 | public static boolean is64Bit() { 44 | return System.getProperty("sun.arch.data.model").contains("64"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/SetupIntelijRunConfigs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.nio.charset.StandardCharsets; 30 | 31 | import org.apache.commons.io.FileUtils; 32 | import org.gradle.api.Project; 33 | 34 | import net.fabricmc.loom.LoomGradleExtension; 35 | import net.fabricmc.loom.providers.MinecraftAssetsProvider; 36 | import net.fabricmc.loom.providers.MinecraftNativesProvider; 37 | 38 | public class SetupIntelijRunConfigs { 39 | public static void setup(Project project) { 40 | LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); 41 | 42 | File projectDir = project.getRootProject().file(".idea"); 43 | 44 | if (!projectDir.exists()) { 45 | return; 46 | } 47 | 48 | try { 49 | generate(project); 50 | } catch (IOException e) { 51 | throw new RuntimeException("Failed to generate run configs", e); 52 | } 53 | 54 | File runDir = new File(project.getRootDir(), extension.runDir); 55 | 56 | if (!runDir.exists()) { 57 | runDir.mkdirs(); 58 | } 59 | } 60 | 61 | private static void generate(Project project) throws IOException { 62 | Project rootProject = project.getRootProject(); 63 | LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); 64 | 65 | if (extension.ideSync()) { 66 | //Ensures the assets are downloaded when idea is syncing a project 67 | MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); 68 | MinecraftNativesProvider.provide(project, extension); 69 | } 70 | 71 | String projectPath = project == rootProject ? "" : project.getPath().replace(':', '_'); 72 | 73 | File projectDir = rootProject.file(".idea"); 74 | File runConfigsDir = new File(projectDir, "runConfigurations"); 75 | File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client" + projectPath + ".xml"); 76 | File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server" + projectPath + ".xml"); 77 | 78 | if (!runConfigsDir.exists()) { 79 | runConfigsDir.mkdirs(); 80 | } 81 | 82 | String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); 83 | String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); 84 | 85 | if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { 86 | FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); 87 | } 88 | 89 | if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { 90 | FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/StaticPathWatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.io.IOException; 28 | import java.nio.file.FileSystems; 29 | import java.nio.file.Files; 30 | import java.nio.file.Path; 31 | import java.nio.file.StandardWatchEventKinds; 32 | import java.nio.file.WatchEvent; 33 | import java.nio.file.WatchKey; 34 | import java.nio.file.WatchService; 35 | import java.util.HashMap; 36 | import java.util.HashSet; 37 | import java.util.Map; 38 | import java.util.Set; 39 | 40 | public final class StaticPathWatcher { 41 | public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); 42 | 43 | private final Set changeCache = new HashSet<>(); 44 | private final WatchService service; 45 | private final Map pathsObserved = new HashMap<>(); 46 | 47 | private StaticPathWatcher() { 48 | try { 49 | service = FileSystems.getDefault().newWatchService(); 50 | } catch (IOException e) { 51 | throw new RuntimeException("Error creating watch service", e); 52 | } 53 | } 54 | 55 | private void pollChanges() { 56 | WatchKey key; 57 | while ((key = service.poll()) != null) { 58 | for (WatchEvent event : key.pollEvents()) { 59 | Object ctx = event.context(); 60 | 61 | if (ctx instanceof Path) { 62 | changeCache.add(((Path) ctx).toAbsolutePath()); 63 | } 64 | } 65 | } 66 | } 67 | 68 | public boolean hasFileChanged(Path filePath) { 69 | if (!Files.exists(filePath)) { 70 | return true; 71 | } 72 | 73 | pollChanges(); 74 | filePath = filePath.toAbsolutePath(); 75 | 76 | if (changeCache.contains(filePath)) { 77 | return true; 78 | } else { 79 | Path parentPath = filePath.getParent(); 80 | 81 | if (!pathsObserved.containsKey(parentPath)) { 82 | try { 83 | pathsObserved.put(parentPath, parentPath.register(service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE)); 84 | 85 | return true; 86 | } catch (IOException e) { 87 | throw new RuntimeException("Error registering watch on " + parentPath, e); 88 | } 89 | } else { 90 | return false; 91 | } 92 | } 93 | } 94 | 95 | public void resetFile(Path file) { 96 | pollChanges(); 97 | 98 | changeCache.remove(file.toAbsolutePath()); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/ThrowingIntObjConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util; 9 | 10 | import java.util.function.ObjIntConsumer; 11 | 12 | public interface ThrowingIntObjConsumer { 13 | void accept(int value, O object) throws T; 14 | 15 | interface IntObjConsumer extends ThrowingIntObjConsumer, ObjIntConsumer { 16 | @Override 17 | default void accept(T object, int value) { 18 | accept(value, object); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util; 26 | 27 | import java.util.Map; 28 | 29 | import net.fabricmc.loom.LoomGradleExtension; 30 | import net.fabricmc.mappings.ClassEntry; 31 | import net.fabricmc.mappings.EntryTriple; 32 | import net.fabricmc.mappings.FieldEntry; 33 | import net.fabricmc.mappings.Mappings; 34 | import net.fabricmc.mappings.MethodEntry; 35 | import net.fabricmc.tinyremapper.IMappingProvider; 36 | import net.fabricmc.tinyremapper.MemberInstance; 37 | 38 | public class TinyRemapperMappingsHelper { 39 | public interface LocalNameSuggestor { 40 | String suggestLocalName(String type, boolean plural); 41 | } 42 | 43 | private TinyRemapperMappingsHelper() { } 44 | 45 | public static IMappingProvider create(LoomGradleExtension extension, Mappings mappings, String from, String to) { 46 | return new IMappingProvider() { 47 | @Override 48 | public void load(Map classMap, Map fieldMap, Map methodMap) { 49 | for (ClassEntry entry : mappings.getClassEntries()) { 50 | classMap.put(entry.get(from), entry.get(to)); 51 | } 52 | 53 | for (FieldEntry entry : mappings.getFieldEntries()) { 54 | add(entry, from, to, fieldMap); 55 | } 56 | 57 | for (MethodEntry entry : mappings.getMethodEntries()) { 58 | EntryTriple fromTriple = entry.get(from); 59 | methodMap.put(fromTriple.getOwner() + '/' + MemberInstance.getMethodId(fromTriple.getName(), fromTriple.getDesc()), entry.get(to).getName()); 60 | } 61 | } 62 | 63 | @Override 64 | public String suggestLocalName(String type, boolean plural) { 65 | for (LocalNameSuggestor suggestor : extension.getLocalSuggestors()) { 66 | String name = suggestor.suggestLocalName(type, plural); 67 | if (name != null) return name; 68 | } 69 | 70 | return IMappingProvider.super.suggestLocalName(type, plural); 71 | } 72 | }; 73 | } 74 | 75 | public static void add(FieldEntry field, String from, String to, Map fields) { 76 | EntryTriple fromTriple = field.get(from); 77 | fields.put(fromTriple.getOwner() + '/' + MemberInstance.getFieldId(fromTriple.getName(), fromTriple.getDesc(), false), field.get(to).getName()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/assets/AssetIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util.assets; 26 | 27 | import java.util.HashSet; 28 | import java.util.LinkedHashMap; 29 | import java.util.Map; 30 | import java.util.Set; 31 | 32 | public class AssetIndex { 33 | private final Map objects; 34 | private boolean virtual; 35 | 36 | public AssetIndex() { 37 | this.objects = new LinkedHashMap<>(); 38 | } 39 | 40 | public Map getFileMap() { 41 | return this.objects; 42 | } 43 | 44 | public Set getUniqueObjects() { 45 | return new HashSet<>(this.objects.values()); 46 | } 47 | 48 | public boolean isVirtual() { 49 | return this.virtual; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/assets/AssetObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util.assets; 26 | 27 | public class AssetObject { 28 | private String hash; 29 | private long size; 30 | 31 | public String getHash() { 32 | return this.hash; 33 | } 34 | 35 | public long getSize() { 36 | return this.size; 37 | } 38 | 39 | @Override 40 | public boolean equals(Object o) { 41 | if (this == o) { 42 | return true; 43 | } else if ((o == null) || (getClass() != o.getClass())) { 44 | return false; 45 | } else { 46 | AssetObject that = (AssetObject) o; 47 | return this.size == that.size && this.hash.equals(that.hash); 48 | } 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | int result = this.hash.hashCode(); 54 | result = 31 * result + (int) (this.size ^ this.size >>> 32); 55 | return result; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/progress/ProgressLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of fabric-loom, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2016, 2017, 2018 FabricMC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net.fabricmc.loom.util.progress; 26 | 27 | import org.gradle.api.Project; 28 | import org.gradle.api.internal.project.ProjectInternal; 29 | import org.gradle.api.logging.Logger; 30 | import org.gradle.internal.logging.progress.ProgressLoggerFactory; 31 | import org.gradle.internal.service.ServiceRegistry; 32 | 33 | /** 34 | * Wrapper to ProgressLogger internal API. 35 | */ 36 | public abstract class ProgressLogger { 37 | protected final Logger logger; 38 | 39 | ProgressLogger(Logger logger) { 40 | this.logger = logger; 41 | } 42 | 43 | /** 44 | * Get a Progress logger from the Gradle internal API. 45 | * 46 | * @param project The project 47 | * @param category The logger category 48 | * @return In any case a progress logger 49 | */ 50 | public static ProgressLogger getProgressFactory(Project project, String category) { 51 | try { 52 | ServiceRegistry registry = ((ProjectInternal) project).getServices(); 53 | ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); 54 | return new ProgressLoggerImpl(project.getLogger(), factory.newOperation(category), factory); 55 | } catch (OutOfMemoryError e) { 56 | throw e; 57 | } catch (Throwable t) { 58 | project.getLogger().error("Unable to get progress logger. Task progress will not be displayed.", t); 59 | return new ProgressLoggerShim(project.getLogger()).setDescription(category); 60 | } 61 | } 62 | 63 | /** 64 | * Returns the description of the operation. 65 | * 66 | * @return the description, must not be empty. 67 | */ 68 | public abstract String getDescription(); 69 | 70 | /** 71 | * Sets the description of the operation. This should be a full, stand-alone description of the operation. 72 | * 73 | *

This must be called before {@link #started()} 74 | * 75 | * @param description The description. 76 | */ 77 | public abstract ProgressLogger setDescription(String description); 78 | 79 | /** 80 | * Convenience method that sets descriptions and logs started() event. 81 | * 82 | * @return this logger instance 83 | */ 84 | public abstract ProgressLogger start(String description, String shortDescription); 85 | 86 | /** 87 | * Logs the start of the operation, with no initial status. 88 | */ 89 | public abstract void started(); 90 | 91 | /** 92 | * Logs the start of the operation, with the given status. 93 | * 94 | * @param status The initial status message. Can be null or empty. 95 | */ 96 | public abstract void started(String status); 97 | 98 | /** 99 | * Logs some progress, indicated by a new status. 100 | * 101 | * @param status The new status message. Can be null or empty. 102 | */ 103 | public abstract void progress(String status); 104 | 105 | /** 106 | * Logs the completion of the operation, with no final status. 107 | */ 108 | public abstract void completed(); 109 | 110 | /** 111 | * Logs the completion of the operation, with a final status. This is generally logged along with the description. 112 | * 113 | * @param status The final status message. Can be null or empty. 114 | * @param failed Whether the operation failed. 115 | */ 116 | public abstract void completed(String status, boolean failed); 117 | 118 | public abstract ProgressLogger newChild(Class category); 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/progress/ProgressLoggerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util.progress; 9 | 10 | import org.gradle.api.logging.Logger; 11 | import org.gradle.internal.logging.progress.ProgressLogger; 12 | import org.gradle.internal.logging.progress.ProgressLoggerFactory; 13 | 14 | class ProgressLoggerImpl extends net.fabricmc.loom.util.progress.ProgressLogger { 15 | private final ProgressLogger progress; 16 | private final ProgressLoggerFactory logFactory; 17 | 18 | ProgressLoggerImpl(Logger logger, ProgressLogger progress, ProgressLoggerFactory logFactory) { 19 | super(logger); 20 | 21 | this.progress = progress; 22 | this.logFactory = logFactory; 23 | } 24 | 25 | @Override 26 | public String getDescription() { 27 | try { 28 | return progress.getDescription(); 29 | } catch (IncompatibleClassChangeError e) { 30 | logger.warn("Error calling ProgressLogger#getDescription", e); 31 | return ""; //Got to return something 32 | } 33 | } 34 | 35 | @Override 36 | public net.fabricmc.loom.util.progress.ProgressLogger setDescription(String description) { 37 | try { 38 | progress.setDescription(description); 39 | } catch (IncompatibleClassChangeError e) { 40 | logger.warn("Error calling ProgressLogger#setDescription", e); 41 | } 42 | 43 | return this; 44 | } 45 | 46 | @Override 47 | public net.fabricmc.loom.util.progress.ProgressLogger start(String description, String shortDescription) { 48 | try { 49 | progress.start(description, shortDescription); 50 | } catch (IncompatibleClassChangeError e) { 51 | logger.warn("Error calling ProgressLogger#start", e); 52 | } 53 | 54 | return this; 55 | } 56 | 57 | @Override 58 | public void started() { 59 | try { 60 | progress.started(); 61 | } catch (IncompatibleClassChangeError e) { 62 | logger.warn("Error calling ProgressLogger#started", e); 63 | } 64 | } 65 | 66 | @Override 67 | public void started(String status) { 68 | try { 69 | progress.started(status); 70 | } catch (IncompatibleClassChangeError e) { 71 | logger.warn("Error calling ProgressLogger#started", e); 72 | } 73 | } 74 | 75 | @Override 76 | public void progress(String status) { 77 | try { 78 | progress.progress(status); 79 | } catch (IncompatibleClassChangeError e) { 80 | logger.warn("Error calling ProgressLogger#progress", e); 81 | } 82 | } 83 | 84 | @Override 85 | public void completed() { 86 | try { 87 | progress.completed(); 88 | } catch (IncompatibleClassChangeError e) { 89 | logger.warn("Error calling ProgressLogger#completed", e); 90 | } 91 | } 92 | 93 | @Override 94 | public void completed(String status, boolean failed) { 95 | try { 96 | progress.completed(status, failed); 97 | } catch (IncompatibleClassChangeError e) { 98 | logger.warn("Error calling ProgressLogger#completed", e); 99 | } 100 | } 101 | 102 | @Override 103 | public net.fabricmc.loom.util.progress.ProgressLogger newChild(Class category) { 104 | try { 105 | return new ProgressLoggerImpl(logger, logFactory.newOperation(category, progress), logFactory); 106 | } catch (IncompatibleClassChangeError e) { 107 | logger.warn("Error calling ProgressLoggerFactory#newOperation", e); 108 | return new ProgressLoggerShim(logger); 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/main/java/net/fabricmc/loom/util/progress/ProgressLoggerShim.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Chocohead 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | package net.fabricmc.loom.util.progress; 9 | 10 | import org.gradle.api.logging.Logger; 11 | 12 | class ProgressLoggerShim extends ProgressLogger { 13 | private String description = ""; 14 | 15 | ProgressLoggerShim(Logger logger) { 16 | super(logger); 17 | } 18 | 19 | @Override 20 | public String getDescription() { 21 | return description; 22 | } 23 | 24 | @Override 25 | public ProgressLogger setDescription(String description) { 26 | this.description = description; 27 | return this; 28 | } 29 | 30 | @Override 31 | public ProgressLogger start(String description, String shortDescription) { 32 | this.description = description; 33 | return this; 34 | } 35 | 36 | @Override 37 | public void started() { 38 | } 39 | 40 | @Override 41 | public void started(String status) { 42 | logger.info("{}-{}", description, status); 43 | } 44 | 45 | @Override 46 | public void progress(String status) { 47 | logger.info("{}-{}", description, status); 48 | } 49 | 50 | @Override 51 | public void completed() { 52 | } 53 | 54 | @Override 55 | public void completed(String status, boolean failed) { 56 | logger.info("{}-{}", description, status); 57 | } 58 | 59 | @Override 60 | public ProgressLogger newChild(Class category) { 61 | return new ProgressLoggerShim(logger).setDescription(category.getName()); 62 | } 63 | } -------------------------------------------------------------------------------- /src/main/resources/eclipse_run_config_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/idea_run_config_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.fabric.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | --------------------------------------------------------------------------------