diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..b15d434 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,27 @@ +name: Publish + +on: + push: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + build: + uses: MinecraftForge/SharedActions/.github/workflows/gradle.yml@main + with: + java: 8 + gradle_tasks: "publish" + artifact_name: "installertools" + secrets: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + PROMOTE_ARTIFACT_WEBHOOK: ${{ secrets.PROMOTE_ARTIFACT_WEBHOOK }} + PROMOTE_ARTIFACT_USERNAME: ${{ secrets.PROMOTE_ARTIFACT_USERNAME }} + PROMOTE_ARTIFACT_PASSWORD: ${{ secrets.PROMOTE_ARTIFACT_PASSWORD }} + MAVEN_USER: ${{ secrets.MAVEN_USER }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + SIGN_KEY_ALIAS: ${{ secrets.SIGN_KEY_ALIAS }} + SIGN_KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }} + SIGN_KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }} + SIGN_KEYSTORE_DATA: ${{ secrets.SIGN_KEYSTORE_DATA }} diff --git a/.teamcity/pom.xml b/.teamcity/pom.xml deleted file mode 100644 index 3da7495..0000000 --- a/.teamcity/pom.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - 4.0.0 - MinecraftForge_InstallerTools Config DSL Script - MinecraftForge_InstallerTools - MinecraftForge_InstallerTools_dsl - 1.0-SNAPSHOT - - - org.jetbrains.teamcity - configs-dsl-kotlin-parent - 1.0-SNAPSHOT - - - - - jetbrains-all - https://download.jetbrains.com/teamcity-repository - - true - - - - teamcity-server - https://teamcity.minecraftforge.net/app/dsl-plugins-repository - - true - - - - - - - JetBrains - https://download.jetbrains.com/teamcity-repository - - - - - ${basedir} - - - kotlin-maven-plugin - org.jetbrains.kotlin - ${kotlin.version} - - - - - compile - process-sources - - compile - - - - test-compile - process-test-sources - - test-compile - - - - - - org.jetbrains.teamcity - teamcity-configs-maven-plugin - ${teamcity.dsl.version} - - kotlin - target/generated-configs - - - - - - - - org.jetbrains.teamcity - configs-dsl-kotlin - ${teamcity.dsl.version} - compile - - - org.jetbrains.teamcity - configs-dsl-kotlin-plugins - 1.0-SNAPSHOT - pom - compile - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - compile - - - org.jetbrains.kotlin - kotlin-script-runtime - ${kotlin.version} - compile - - - \ No newline at end of file diff --git a/.teamcity/settings.kts b/.teamcity/settings.kts deleted file mode 100644 index e614b5b..0000000 --- a/.teamcity/settings.kts +++ /dev/null @@ -1,71 +0,0 @@ -import jetbrains.buildServer.configs.kotlin.v2019_2.* -import jetbrains.buildServer.configs.kotlin.v2019_2.projectFeatures.githubIssues - -/* -The settings script is an entry point for defining a TeamCity -project hierarchy. The script should contain a single call to the -project() function with a Project instance or an init function as -an argument. - -VcsRoots, BuildTypes, Templates, and subprojects can be -registered inside the project using the vcsRoot(), buildType(), -template(), and subProject() methods respectively. - -To debug settings scripts in command-line, run the - - mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate - -command and attach your debugger to the port 8000. - -To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View --> Tool Windows -> Maven Projects), find the generate task node -(Plugins -> teamcity-configs -> teamcity-configs:generate), the -'Debug' option is available in the context menu for the task. -*/ - -version = "2021.2" - -project { - - buildType(Build) - buildType(BuildSecondaryBranches) - buildType(PullRequests) - - params { - text("git_main_branch", "master", label = "Git Main Branch", description = "The git main or default branch to use in VCS operations.", display = ParameterDisplay.HIDDEN, allowEmpty = false) - text("github_repository_name", "InstallerTools", label = "The github repository name. Used to connect to it in VCS Roots.", description = "This is the repository slug on github. So for example `InstallerTools` or `MinecraftForge`. It is interpolated into the global VCS Roots.", display = ParameterDisplay.HIDDEN, allowEmpty = false) - text("env.PUBLISHED_JAVA_ARTIFACT_ID", "installertools", label = "Published artifact id", description = "The maven coordinate artifact id that has been published by this build. Can not be empty.", allowEmpty = false) - text("env.PUBLISHED_JAVA_GROUP", "net.minecraftforge", label = "Published group", description = "The maven coordinate group that has been published by this build. Can not be empty.", allowEmpty = false) - text("docker_gradle_version", "7.4.2") - text("docker_jdk_version", "8") - } - - features { - githubIssues { - id = "InstallerTools__IssueTracker" - displayName = "MinecraftForge/InstallerTools" - repositoryURL = "https://github.com/MinecraftForge/InstallerTools" - } - } -} - -object Build : BuildType({ - templates(AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_BuildMainBranches"), AbsoluteId("MinecraftForge_BuildUsingGradle"), AbsoluteId("MinecraftForge_PublishProjectUsingGradle"), AbsoluteId("MinecraftForge_TriggersStaticFilesWebpageGenerator")) - id("InstallerTools__Build") - name = "Build" - description = "Builds and Publishes the main branches of the project." -}) - -object BuildSecondaryBranches : BuildType({ - templates(AbsoluteId("MinecraftForge_ExcludesBuildingDefaultBranch"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_BuildMainBranches"), AbsoluteId("MinecraftForge_BuildUsingGradle")) - id("InstallerTools__BuildSecondaryBranches") - name = "Build - Secondary Branches" - description = "Builds and Publishes the secondary branches of the project." -}) - -object PullRequests : BuildType({ - templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_BuildUsingGradle")) - id("InstallerTools__PullRequests") - name = "Pull Requests" - description = "Builds pull requests for the project" -}) diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index ff951af..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,78 +0,0 @@ -@Library('forge-shared-library')_ - -pipeline { - agent { - docker { - image 'gradle:jdk8' - args '-v gradlecache:/gradlecache' - } - } - environment { - GRADLE_ARGS = '-Dorg.gradle.daemon.idletimeout=5000' - DISCORD_WEBHOOK = credentials('forge-discord-jenkins-webhook') - DISCORD_PREFIX = "Job: InstallerTools Branch: ${BRANCH_NAME} Build: #${BUILD_NUMBER}" - JENKINS_HEAD = 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png' - } - - stages { - stage('notify_start') { - when { - not { - changeRequest() - } - } - steps { - discordSend( - title: "${DISCORD_PREFIX} Started", - successful: true, - result: 'ABORTED', //White border - thumbnail: JENKINS_HEAD, - webhookURL: DISCORD_WEBHOOK - ) - } - } - stage('buildandtest') { - steps { - sh './gradlew ${GRADLE_ARGS} --refresh-dependencies --continue build test' - script { - gradleVersion(this) - } - } - } - stage('publish') { - when { - not { - changeRequest() - } - } - steps { - withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) { - withGradle { - sh './gradlew ${GRADLE_ARGS} publish' - } - } - } - post { - success { - build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote ${env.MYGROUP}:${env.MYARTIFACT} ${env.MYVERSION} latest")], propagate: false, wait: false - } - } - } - } - post { - always { - script { - if (env.CHANGE_ID == null) { // This is unset for non-PRs - discordSend( - title: "${DISCORD_PREFIX} Finished ${currentBuild.currentResult}", - description: '```\n' + getChanges(currentBuild) + '\n```', - successful: currentBuild.resultIsBetterOrEqualTo("SUCCESS"), - result: currentBuild.currentResult, - thumbnail: JENKINS_HEAD, - webhookURL: DISCORD_WEBHOOK - ) - } - } - } - } -} \ No newline at end of file diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/build.gradle b/build.gradle index 9c6dfc7..34424ab 100644 --- a/build.gradle +++ b/build.gradle @@ -1,97 +1,88 @@ +import net.minecraftforge.gradleutils.PomUtils + plugins { - id 'java-library' - id 'maven-publish' - id 'eclipse' - id 'org.cadixdev.licenser' version '0.6.1' - id 'com.github.johnrengelman.shadow' version '7.1.2' - id 'com.github.ben-manes.versions' version '0.42.0' - id 'net.minecraftforge.gradleutils' version '2.+' + id 'java-library' + id 'maven-publish' + id 'eclipse' + id 'org.cadixdev.licenser' version '0.6.1' + id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.github.ben-manes.versions' version '0.49.0' + id 'net.minecraftforge.gradleutils' version '[2.1.2,)' + id 'net.minecraftforge.gradlejarsigner' version '1.0.4' } group = 'net.minecraftforge' - -version = gradleutils.getTagOffsetVersion() -println('Version: ' + version) -java.toolchain.languageVersion = JavaLanguageVersion.of(8) +version = gradleutils.tagOffsetVersion +println("Version: $version") +jarSigner.autoDetect('forge') repositories { mavenCentral() - maven { url 'https://maven.minecraftforge.net/' } + maven gradleutils.forgeMaven } license { - header project.file('LICENSE-header.txt') - include 'net/minecraftforge/installertools/**/*.java' + header file('LICENSE-header.txt') newLine false } -jar { - manifest.attributes('Main-Class': 'net.minecraftforge.installertools.ConsoleTool') - manifest.attributes('Implementation-Version': project.version) +java { + toolchain.languageVersion = JavaLanguageVersion.of(8) + withSourcesJar() } -shadowJar { - classifier 'fatjar' - manifest.attributes('Main-Class': 'net.minecraftforge.installertools.ConsoleTool') - manifest.attributes('Implementation-Version': project.version) + +tasks.named('jar').configure { + manifest { + attributes([ + 'Main-Class': 'net.minecraftforge.installertools.ConsoleTool', + 'Specification-Title': 'Installer Tools', + 'Specification-Vendor': 'Forge Development LLC', + 'Specification-Version': gradleutils.gitInfo.tag, + 'Implementation-Title': "$project.group:$project.name", + 'Implementation-Vendor': 'Forge Development LLC', + 'Implementation-Version': project.version + ] as LinkedHashMap) + } + jarSigner.sign(it) } -task sourcesJar(type: Jar) { - archiveClassifier = 'sources' - from sourceSets.main.allSource +tasks.named('shadowJar').configure { + archiveClassifier = 'fatjar' + jarSigner.sign(it) } artifacts { - archives jar archives shadowJar - archives sourcesJar } dependencies { - implementation 'net.sf.jopt-simple:jopt-simple:5.0.4' - implementation 'com.google.code.gson:gson:2.8.7' - implementation 'net.md-5:SpecialSource:1.11.0' - implementation 'de.siegmar:fastcsv:2.0.0' - implementation 'net.minecraftforge:srgutils:0.4.11' - implementation 'org.ow2.asm:asm-commons:9.3' + implementation 'net.sf.jopt-simple:jopt-simple:6.0-alpha-3' + implementation 'com.google.code.gson:gson:2.10.1' + implementation 'de.siegmar:fastcsv:2.2.2' + implementation 'net.minecraftforge:srgutils:0.5.6' + implementation 'org.ow2.asm:asm-commons:9.6' } publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourcesJar + publications.register('mavenJava', MavenPublication) { + from components.java + artifactId = 'installertools' + pom { + name = 'Installer Tools' + description = 'A collection of command line tools that are useful for the Forge installer, that are not worth being their own standalone projects.' + url = 'https://github.com/MinecraftForge/InstallerTools' + PomUtils.setGitHubDetails(pom, 'MergeTool') - pom { - name = 'Installer Tools' - description = 'A collection of command line tools that are useful for the Forge installer, that are not worth being their own standalone projects.' - url = 'https://github.com/MinecraftForge/InstallerTools' - scm { - url = 'https://github.com/MinecraftForge/InstallerTools' - connection = 'scm:git:git://github.com/MinecraftForge/InstallerTools.git' - developerConnection = 'scm:git:git@github.com:MinecraftForge/InstallerTools.git' - } - issueManagement { - system = 'github' - url = 'https://github.com/MinecraftForge/InstallerTools/issues' - } + PomUtils.setGitHubDetails(pom, 'MergeTool') - licenses { - license { - name = 'LGPLv2.1' - url = 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt' - } - } + license PomUtils.Licenses.LGPLv2_1 - developers { - developer { - id = 'LexManos' - name = 'Lex Manos' - } - } + developers { + developer PomUtils.Developers.LexManos } } } repositories { - maven gradleutils.getPublishingForgeMaven() + maven gradleutils.publishingForgeMaven } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927..7f93135 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..3fa8f86 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd3..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/settings.gradle b/settings.gradle index d1016e5..4959f64 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,4 +5,9 @@ pluginManagement { } } -rootProject.name = 'installertools' +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' +} + + +rootProject.name = 'InstallerTools' diff --git a/src/main/java/net/minecraftforge/installertools/DeobfRealms.java b/src/main/java/net/minecraftforge/installertools/DeobfRealms.java deleted file mode 100644 index e5f37d1..0000000 --- a/src/main/java/net/minecraftforge/installertools/DeobfRealms.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * InstallerTools - * Copyright (c) 2019-2021. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package net.minecraftforge.installertools; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; - -import joptsimple.OptionException; -import joptsimple.OptionParser; -import joptsimple.OptionSet; -import joptsimple.OptionSpec; -import net.md_5.specialsource.Jar; -import net.md_5.specialsource.JarMapping; -import net.md_5.specialsource.JarRemapper; -import net.md_5.specialsource.ProgressMeter; -import net.md_5.specialsource.SpecialSource; -import net.md_5.specialsource.provider.JarProvider; -import net.md_5.specialsource.provider.JointProvider; -import net.minecraftforge.installertools.util.HashFunction; -import net.minecraftforge.installertools.util.VersionJson; -import net.minecraftforge.installertools.util.VersionJson.Library; -import net.minecraftforge.installertools.util.VersionJson.LibraryDownload; - -public class DeobfRealms extends Task { - - @Override - public void process(String[] args) throws IOException { - - OptionParser parser = new OptionParser(); - OptionSpec mapO = parser.accepts("map").withRequiredArg().ofType(File.class).required(); - OptionSpec mcpO = parser.accepts("mcp").withRequiredArg().ofType(String.class).required(); - OptionSpec mcJarO = parser.accepts("mc").withRequiredArg().ofType(File.class).required(); - OptionSpec jsonO = parser.accepts("json").withRequiredArg().ofType(File.class); - OptionSpec libsO = parser.accepts("libs").withRequiredArg().ofType(File.class); - - try { - OptionSet options = parser.parse(args); - - File map = options.valueOf(mapO); - String mcp = options.valueOf(mcpO); - File mcJar = options.valueOf(mcJarO); - File json = options.has(jsonO) ? options.valueOf(jsonO) : new File(mcJar.getAbsolutePath().substring(0, mcJar.getAbsolutePath().length() - 4) + ".json"); // .jar -> .json As long as the launcher doesn't change this structure we're fine. - File libs = options.has(libsO) ? options.valueOf(libsO) : new File(mcJar.getParentFile().getParentFile().getParentFile(), "libraries"); // './versions/version/version.jar' -> './libraries/' - - log("Jar: " + mcJar); - //TODO: Think about sided processors next time a breaking change is needed anyway - if (mcJar.getName().contains("server")) { - log("Detected server jar, skipping client-only DEOBF_REALMS processor"); - return; - } - // By this time, we should have the libraries folder, the mc jar, and the mc json. As the installer should have downloaded/created them. - log("Map: " + map); - log("MCP: " + mcp); - log("Json: " + json); - log("Libs: " + libs); - - if (!map.exists()) - error("Missing required Map: " + map); - if (!mcJar.exists()) - error("Missing required MC jar: " + mcJar); - if (!json.exists()) - error("Missing required Json: " + json); - if (!libs.exists()) - error("Missing required Library Directory: " + libs); - - log("Loading Json: " + json); - VersionJson jsonData = VersionJson.load(json); - - if (jsonData.libraries == null) { - log("No libraries, assuming no realms in this version"); - return; - } - - log("Scanning Libraries: "); - Library realms = null; - for (Library tmp : jsonData.libraries) { - log(" " + tmp.name); - if ("com.mojang".equals(tmp.getArtifact().getGroup()) && - "realms".equals(tmp.getArtifact().getName())) { - realms = tmp; - break; - } - } - - if (realms == null) { - log("No \"com.mojang:realms\" library found, assuming realms disabled for this version."); - return; - } - - LibraryDownload artifact = realms.downloads == null ? null : realms.downloads.artifact; - String path = artifact == null ? realms.getArtifact().getPath() : realms.downloads.artifact.path; - - File vanilla = new File(libs, path); - File target = new File(libs, path.substring(0, path.length() - 4) + '-' + mcp + ".jar"); - - if (target.exists()) { - log("Target \"" + target.getAbsolutePath() + "\" exists, Assuming job done"); - return; - } - - if (!target.getParentFile().exists() && !target.getParentFile().mkdirs()) - error("Can not create parent directory \"" + target.getParentFile().getAbsolutePath() +"\" Aborting."); - - if (!vanilla.exists()) { - if (artifact == null || artifact.url == null) - error("Can not downloaad missing realms jar \"" + vanilla.getAbsolutePath() + "\" and no download information avalible."); - if (!download(vanilla, artifact.url.toString(), artifact.sha1)) - error("Failed to download realms jar"); - } - - JarMapping mapping = new JarMapping(); - mapping.loadMappings(map); - - setVerbose(); - - try (Jar vanillaJar = Jar.init(vanilla); - Jar mcSSJar = Jar.init(mcJar)) { - JointProvider inheritanceProviders = new JointProvider(); - inheritanceProviders.add(new JarProvider(vanillaJar)); - inheritanceProviders.add(new JarProvider(mcSSJar)); - mapping.setFallbackInheritanceProvider(inheritanceProviders); - - JarRemapper remapper = new JarRemapper(mapping); - try { - remapper.remapJar(vanillaJar, target); - } catch (IOException e) { - if (target.exists()) - target.delete(); - throw new RuntimeException(e); - } - } - - log("Process complete"); - } catch (OptionException e) { - parser.printHelpOn(System.out); - e.printStackTrace(); - } - } - - private void setVerbose() { - try { - ProgressMeter.printInterval = 10; - Field verbose = SpecialSource.class.getDeclaredField("verbose"); - verbose.setAccessible(true); - verbose.set(null, true); - } catch (Throwable e) { - log("Could not set verbose. Log may appear to freeze, it's not."); - } - } - - private boolean download(File target, String url, String targetSha1) { - log(" Downloading library from " + url); - try { - URLConnection connection = getConnection(url); - if (connection != null) { - Files.copy(connection.getInputStream(), target.toPath(), StandardCopyOption.REPLACE_EXISTING); - - if (targetSha1 != null) { - String actualSha1 = HashFunction.SHA1.hashNullable(target); - if (targetSha1.equals(actualSha1)) { - log(" Download completed: Checksum validated."); - return true; - } - log(" Download failed: Checksum invalid, deleting file:"); - log(" Expected: " + targetSha1); - log(" Actual: " + actualSha1); - if (!target.delete()) { - log(" Failed to delete file, aborting."); - return false; - } - } - log(" Download completed: No checksum, Assuming valid."); - } - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } - - private URLConnection getConnection(String address) { - try { - int MAX = 3; - URL url = new URL(address); - URLConnection connection = null; - for (int x = 0; x < MAX; x++) { //Maximum of 3 redirects. - connection = url.openConnection(); - connection.setConnectTimeout(5000); - connection.setReadTimeout(5000); - if (connection instanceof HttpURLConnection) { - HttpURLConnection hcon = (HttpURLConnection)connection; - hcon.setInstanceFollowRedirects(false); - int res = hcon.getResponseCode(); - if (res == HttpURLConnection.HTTP_MOVED_PERM || res == HttpURLConnection.HTTP_MOVED_TEMP) { - String location = hcon.getHeaderField("Location"); - hcon.disconnect(); //Kill old connection. - if (x == MAX-1) { - log("Invalid number of redirects: " + location); - return null; - } else { - log("Following redirect: " + location); - url = new URL(url, location); // Nested in case of relative urls. - } - } else { - break; - } - } else { - break; - } - } - return connection; - } catch (IOException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/src/main/java/net/minecraftforge/installertools/DownloadMojmaps.java b/src/main/java/net/minecraftforge/installertools/DownloadMojmaps.java index c203624..c987619 100644 --- a/src/main/java/net/minecraftforge/installertools/DownloadMojmaps.java +++ b/src/main/java/net/minecraftforge/installertools/DownloadMojmaps.java @@ -26,6 +26,8 @@ import joptsimple.OptionSpec; import net.minecraftforge.installertools.util.ManifestJson; import net.minecraftforge.installertools.util.VersionJson; +import net.minecraftforge.srgutils.IMappingFile; +import net.minecraftforge.srgutils.IMappingFile.Format; import java.io.File; import java.io.IOException; @@ -33,6 +35,7 @@ import java.io.InputStreamReader; import java.net.URL; import java.nio.file.Files; +import java.nio.file.StandardCopyOption; public class DownloadMojmaps extends Task { private static final String MANIFEST_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json"; @@ -44,23 +47,36 @@ public void process(String[] args) throws IOException { OptionSpec versionO = parser.accepts("version").withRequiredArg().ofType(String.class).required(); OptionSpec sideO = parser.accepts("side").withRequiredArg().ofType(String.class).required(); OptionSpec outputO = parser.accepts("output").withRequiredArg().ofType(File.class).required(); + OptionSpec sanitizeO = parser.accepts("sanitize"); + OptionSpec formatO = parser.accepts("format").withRequiredArg().ofType(Format.class); + OptionSpec skipIfExistsO = parser.accepts("skipIfExists"); try { OptionSet options = parser.parse(args); String mcversion = options.valueOf(versionO); String side = options.valueOf(sideO); - File output = options.valueOf(outputO); + File output = options.valueOf(outputO).getAbsoluteFile(); + boolean sanitize = options.has(sanitizeO); + Format format = !options.has(formatO) ? Format.TSRG : options.valueOf(formatO); + boolean skip = options.has(skipIfExistsO); log("MC Version: " + mcversion); log("Side: " + side); log("Output: " + output); + log("Sanitize: " + sanitize); + log("Format: " + format); + log("Skip: " + skip); - if (output.exists() && !output.delete()) - error("Could not delete output file: " + output); + // Just trust it, The preferred method is to use the sanitized format and use the installer's output caching but this is added just in case. + if (output.exists() && skip) { + log("Skipping as output file exists"); + return; + } - if (!output.getParentFile().exists() && !output.getParentFile().mkdirs()) - error("Could not make output folders: " + output.getParentFile()); + File parent = output.getParentFile(); + if (parent != null && !parent.exists() && !parent.mkdirs()) + error("Could not make output folders: " + parent); try (InputStream manIn = new URL(MANIFEST_URL).openStream()) { URL url = GSON.fromJson(new InputStreamReader(manIn), ManifestJson.class).getUrl(mcversion); @@ -76,7 +92,17 @@ public void process(String[] args) throws IOException { if (download == null || download.url == null) error("Missing download info for " + side + " mappings"); - Files.copy(download.url.openStream(), output.toPath()); + if (sanitize) { + try (InputStream is = download.url.openStream()) { + // Sending it through the load/write process nukes all the comments and other things that may be in the file. + // As well as sorts things. So it *should* result in the same output file as long as Mojang doesn't change + // any of the actual functional content of the file + IMappingFile map = IMappingFile.load(is); + map.write(output.toPath(), format, false); + } + } else { + Files.copy(download.url.openStream(), output.toPath(), StandardCopyOption.REPLACE_EXISTING); + } log("Downloaded Mojang mappings for " + mcversion); } } diff --git a/src/main/java/net/minecraftforge/installertools/Tasks.java b/src/main/java/net/minecraftforge/installertools/Tasks.java index dd70cec..59de36d 100644 --- a/src/main/java/net/minecraftforge/installertools/Tasks.java +++ b/src/main/java/net/minecraftforge/installertools/Tasks.java @@ -24,7 +24,6 @@ public enum Tasks { MCP_DATA(McpData::new), CREATE_DIR(CreateDirectory::new), CREATE_PARENTS(CreateParents::new), - DEOBF_REALMS(DeobfRealms::new), SRG_TO_MCP(SrgMcpRenamer::new), EXTRACT_INHERITANCE(ExtractInheritance::new), CHAIN_MAPPING(ChainMappings::new), diff --git a/src/main/java/net/minecraftforge/installertools/util/Artifact.java b/src/main/java/net/minecraftforge/installertools/util/Artifact.java index 5e9ac30..bd26d9b 100644 --- a/src/main/java/net/minecraftforge/installertools/util/Artifact.java +++ b/src/main/java/net/minecraftforge/installertools/util/Artifact.java @@ -18,9 +18,6 @@ */ package net.minecraftforge.installertools.util; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; - import java.io.File; import java.util.Locale; @@ -42,7 +39,7 @@ public static Artifact from(String descriptor) { Artifact ret = new Artifact(); ret.descriptor = descriptor; - String[] pts = Iterables.toArray(Splitter.on(':').split(descriptor), String.class); + String[] pts = descriptor.split(":"); ret.group = pts[0]; ret.name = pts[1];