From 5afe3c050c2e4fc1e2df7b4e5cb07de4d9c2f1a0 Mon Sep 17 00:00:00 2001 From: LexManos Date: Tue, 22 Sep 2026 16:16:56 -0700 Subject: [PATCH] Migrate to fully declarative ForgeGradlePlugin and local build-logic --- .gitignore | 3 + build-logic/build.gradle | 42 +++ build-logic/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45457 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + build-logic/gradlew | 251 ++++++++++++++++++ build-logic/gradlew.bat | 94 +++++++ build-logic/settings.gradle | 30 +++ .../forge/build/ConventionExtension.groovy | 147 ++++++++++ .../forge/build/ConventionPlugin.groovy | 95 +++++++ .../minecraftforge/forge/build/Meta.groovy | 72 +++++ .../minecraftforge/forge/build/Runs.groovy | 163 ++++++++++++ .../forge/build/VersionsExtension.java | 41 +++ .../forge/build/WriteForgeVersionJson.groovy | 42 +++ build.gradle | 235 +++------------- fmlcore/build.gradle | 70 +---- fmlearlydisplay/build.gradle | 95 +------ fmlloader/build.gradle | 126 ++------- forge-transformers/build.gradle | 67 +---- gradle/buildLibs.versions.toml | 7 + gradle/earlyDisplayLibs.versions.toml | 6 + gradle/earlyDisplayTestLibs.versions.toml | 9 + gradle/libs.versions.toml | 124 +++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 46175 -> 47505 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- javafmllanguage/build.gradle | 69 +---- lowcodelanguage/build.gradle | 69 +---- mclanguage/build.gradle | 69 +---- settings.gradle | 174 +----------- 28 files changed, 1234 insertions(+), 877 deletions(-) create mode 100644 build-logic/build.gradle create mode 100644 build-logic/gradle/wrapper/gradle-wrapper.jar create mode 100644 build-logic/gradle/wrapper/gradle-wrapper.properties create mode 100644 build-logic/gradlew create mode 100644 build-logic/gradlew.bat create mode 100644 build-logic/settings.gradle create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionExtension.groovy create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionPlugin.groovy create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/Meta.groovy create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/Runs.groovy create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/VersionsExtension.java create mode 100644 build-logic/src/main/groovy/net/minecraftforge/forge/build/WriteForgeVersionJson.groovy create mode 100644 gradle/buildLibs.versions.toml create mode 100644 gradle/earlyDisplayLibs.versions.toml create mode 100644 gradle/earlyDisplayTestLibs.versions.toml create mode 100644 gradle/libs.versions.toml diff --git a/.gitignore b/.gitignore index c134175e62..9d00886d54 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ forgedev #idea /.idea +/build-logic/.idea/ /*/out /classes *.iml @@ -36,7 +37,9 @@ src/minecraft /projects/**/build/ /projects/**/out/ /projects/**/run/ +/*/runs/ /projects/**/*.launch +*.launch /repo/ /rejects-*/ src/*/generated/**/.cache/ diff --git a/build-logic/build.gradle b/build-logic/build.gradle new file mode 100644 index 0000000000..b2b08c4272 --- /dev/null +++ b/build-logic/build.gradle @@ -0,0 +1,42 @@ +plugins { + id("groovy-gradle-plugin") + alias(libs.plugins.licenser) +} + +repositories { + mavenCentral() + gradlePluginPortal() + maven { url = 'https://maven.minecraftforge.net/' } + //mavenLocal() +} + +dependencies { + compileOnly gradleApi() + + // Manually import plugins so that we can apply them by id. + implementation plugin('licenser') + implementation plugin('gradleutils') + implementation plugin('gitversion') + implementation plugin('changelog') + implementation plugin('forgedev') +} + +gradlePlugin { + plugins { + register('convention') { + id = 'net.minecraftforge.forge.build.convention' + implementationClass = 'net.minecraftforge.forge.build.ConventionPlugin' + } + } +} + +final Provider plugin(String alias) { + return (Provider)project.extensions.getByType(VersionCatalogsExtension) + .named("libs") + .findPlugin(alias).get() + .map { it.pluginId + ":" + it.pluginId + ".gradle.plugin:" + it.version } +} + +license { + header = file('../LICENSE-header.txt') +} diff --git a/build-logic/gradle/wrapper/gradle-wrapper.jar b/build-logic/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..8bdaf60c75ab801e22807dde59e12a8735a34077 GIT binary patch literal 45457 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 c82=K%QXLKFx%@O{wJjEi6Y56o#$)Bpeg literal 0 HcmV?d00001 diff --git a/build-logic/gradle/wrapper/gradle-wrapper.properties b/build-logic/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..c42672d95b --- /dev/null +++ b/build-logic/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/build-logic/gradlew b/build-logic/gradlew new file mode 100644 index 0000000000..ef07e0162b --- /dev/null +++ b/build-logic/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + 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 +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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, 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" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# 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. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat new file mode 100644 index 0000000000..db3a6ac207 --- /dev/null +++ b/build-logic/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/build-logic/settings.gradle b/build-logic/settings.gradle new file mode 100644 index 0000000000..58bda31eae --- /dev/null +++ b/build-logic/settings.gradle @@ -0,0 +1,30 @@ +pluginManagement { + + repositories { + gradlePluginPortal() + maven { url = 'https://maven.minecraftforge.net/' } + mavenLocal() + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' +} + +//enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS' + +dependencyResolutionManagement.versionCatalogs { + register('bootLibs') { + description = 'Important version numbers that are externally declared for easy modification.' + from(files('../minecraft.versions.toml')) + } + + create('libs') { + description = 'Libraries used by Forge and its subprojects.' + from(files("../gradle/libs.versions.toml")) + } +} + +if (new File('forgedev/settings.gradle').exists()) + includeBuild '../forgedev' + diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionExtension.groovy b/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionExtension.groovy new file mode 100644 index 0000000000..6c36a720f5 --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionExtension.groovy @@ -0,0 +1,147 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build + +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ExternalModuleDependencyBundle +import org.gradle.api.artifacts.MinimalExternalModuleDependency +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.TaskProvider +import org.gradle.jvm.tasks.Jar +import org.jspecify.annotations.Nullable + +import javax.inject.Inject + +@CompileStatic +abstract class ConventionExtension implements Meta { + private final Project project; + private final Runs runs + + protected abstract @Inject ObjectFactory getObjects() + protected abstract @Inject ProviderFactory getProviders() + + @Inject + ConventionExtension(Project project) { + this.project = project + this.runs = objects.newInstance(Runs, this) + } + + @Override + Project getProject() { + this.project + } + + void manifest(String pkg) { + this.project.tasks.named('jar', Jar).configure { + this.gradleutils.manifestDefaults(it.manifest, pkg) + } + } + void manifest(String pkg, Map info) { + manifest(pkg) + this.project.tasks.named('jar', Jar).configure { + it.manifest.getAttributes().with { + for (var entry : info.entrySet()) + put(entry.key, entry.value) + } + } + } + + // region Maven publishing ============================================================== + void publish() { + publish(pub -> pub.from(project.components.getByName('java'))) + } + void publish(Action config) { + project.with { + publishing.with { + repositories.with { + maven gradleutils.publishingForgeMaven + } + publications.register('mavenJava', MavenPublication) { + changelog.publish(it) + gradleutils.promote(it) + + // The actual artifacts to be published should be configured, so run the config + config.execute(it) + + it.pom.with { + description = project.description + gradleutils.pom.addRemoteDetails(it) + license.with { + gradleutils.pom.licenses.LGPLv2_1 + } + } + } + } + } + } + // endregion + + // region Runs ================================================================ + private TaskProvider genAllData = null + TaskProvider getGenAllData() { + if (genAllData == null) + genAllData = this.project.tasks.register('genAllData') + return genAllData + } + TaskProvider getGenAllData(Action config) { + getGenAllData().configure(config) + return getGenAllData() + } + + void basicRuns() { + this.runs.apply(null, null) + } + + void basicRuns(String mods, File output) { + this.runs.apply(mods, output) + } + void testRuns(String mods, File output) { + this.runs.applyTest(mods, output) + } + // endregion + + // region Forge Version Json =================================================== + private TaskProvider writeForgeVersionJson = null + TaskProvider getForgeVersionJson() { + if (writeForgeVersionJson == null) { + writeForgeVersionJson = this.project.tasks.register('writeForgeVersionJson', WriteForgeVersionJson) + final versions = this.versions + writeForgeVersionJson.configure { + it.forgeVersion.set(versions.forge) + it.minecraftVersion.set(versions.minecraft) + it.mcpVersion.set(versions.mcp) + } + } + return writeForgeVersionJson + } + TaskProvider forgeVersionJson(Action config) { + forgeVersionJson.configure(config) + return forgeVersionJson + } + // endregion + + // region Natives helper ========================================================= + // See gradle/gradle#35070 (https://github.com/gradle/gradle/issues/35070) + // We are making the list of providers first BEFORE mapping them to a provider of the resolved objects so + // that they can be finalized after configuration. + List nativeVariants(Provider bundle) { + final natives = "natives-" + forgedev.os + final deps = this.project.dependencies + bundle.get().collect { dep -> + (deps.variantOf(providers.provider { (MinimalExternalModuleDependency)dep }) { + it.classifier(natives) + }).get() + } + } + // endregion +} diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionPlugin.groovy b/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionPlugin.groovy new file mode 100644 index 0000000000..9d600cebab --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/ConventionPlugin.groovy @@ -0,0 +1,95 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build + +import groovy.transform.CompileStatic +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.jvm.toolchain.JavaLanguageVersion + +@CompileStatic +class ConventionPlugin implements Plugin, Meta { + Project project + @Override + Project getProject() { + this.project + } + + @Override + void apply(Project project) { + this.project = project + project.with { + pluginManager.with { + apply 'java-library' + apply 'maven-publish' + apply pluginId('licenser') + apply pluginId('gradleutils') + apply pluginId('gitversion') + apply pluginId('changelog') + apply pluginId('forgedev') + } + + final versions = extensions.create("versions", VersionsExtension, project) + final convention = extensions.create('convention', ConventionExtension, project) + + logger.lifecycle(name + " " + version) + + gradleutils.with { + vendor.set('Forge Development LLC') + version.set(gitversion.version) + } + project.setGroup('net.minecraftforge') + + java.with { + toolchain.languageVersion.set(JavaLanguageVersion.of(versions.java)) + // This is needed for IDE runtime classpath to be correct/not have multiple of the same artifact + consistentResolution { + it.useCompileClasspathVersions() + } + // Forge needs to build its own sources jar due to patching, everything else should use the default + if (project != rootProject) + it.withSourcesJar() + } + + tasks.withType(JavaCompile).configureEach { + it.options.with { + encoding = 'UTF-8' + compilerArgs << '-Xlint:-unchecked' // This is mainly for vanilla code, but just makes it quiet down outside the IDE + } + } + + // NOTE: We are adding dependencies to projects instead of through settings, so we don't have to apply forgedev in settings. + // Applying forgedev in settings will break IDE linting support, which makes it very hard to work with. + // We can reconsider this if/when JetBrains gets their shit together. + // - I doubt they will ever fix their shit 8/28/2006 - Lex + repositories.with { + // Libraries has to be before maven central because Mojang hosts a classifer that central doesn't (org.lwjgl:lwjgl-freetype:3.3.3:natives-macos-patch) + maven { url = 'https://libraries.minecraft.net/' } + mavenCentral() + maven gradleutils.forgeMaven + project.pluginManager.withPlugin('net.minecraftforge.forgedev') { + maven forgedev.mavenizer + } + + mavenLocal() + } + + changelog.with { + from versions.changelogBase + } + + license.with { + header = rootProject.file('LICENSE-header.txt') + } + + // Common dependencies, + project.dependencies.with { + add('compileOnly', libs.findLibrary('jetbrains.annotations').get()) + } + } + } +} diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/Meta.groovy b/build-logic/src/main/groovy/net/minecraftforge/forge/build/Meta.groovy new file mode 100644 index 0000000000..e2100afa7a --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/Meta.groovy @@ -0,0 +1,72 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build + +import groovy.transform.CompileStatic +import net.minecraftforge.forgedev.ForgeDevExtension +import net.minecraftforge.gitversion.gradle.GitVersionExtension +import net.minecraftforge.gitversion.gradle.changelog.ChangelogExtension +import net.minecraftforge.gradleutils.GradleUtilsExtensionForProject +import net.minecraftforge.licenser.LicenseExtension +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.plugins.ExtraPropertiesExtension +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.publish.PublishingExtension + +@CompileStatic +interface Meta { + Project getProject(); + + default VersionCatalog getLibs() { + project.extensions.getByType(VersionCatalogsExtension).named("libs") + } + + default ExtraPropertiesExtension getExt() { + project.extensions.getByType(ExtraPropertiesExtension) + } + + default JavaPluginExtension getJava() { + project.extensions.getByType(JavaPluginExtension) + } + + default GradleUtilsExtensionForProject getGradleutils() { + project.extensions.getByType(GradleUtilsExtensionForProject) + } + + default GitVersionExtension getGitversion() { + project.extensions.getByType(GitVersionExtension) + } + + default ForgeDevExtension getForgedev() { + project.extensions.getByType(ForgeDevExtension) + } + + default ChangelogExtension getChangelog() { + project.extensions.getByType(ChangelogExtension) + } + + default LicenseExtension getLicense() { + project.extensions.getByType(LicenseExtension) + } + + default PublishingExtension getPublishing() { + project.extensions.getByType(PublishingExtension) + } + + default VersionsExtension getVersions() { + project.extensions.getByType(VersionsExtension) + } + + default ConventionExtension getConvention() { + project.extensions.getByType(ConventionExtension) + } + + default String pluginId(String alias) { + getLibs().findPlugin(alias).orElseThrow { new IllegalStateException("Could not find plugin " + alias) }.get().pluginId + } +} diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/Runs.groovy b/build-logic/src/main/groovy/net/minecraftforge/forge/build/Runs.groovy new file mode 100644 index 0000000000..f7c873a138 --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/Runs.groovy @@ -0,0 +1,163 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build + +import groovy.transform.CompileStatic +import org.gradle.api.Project +import org.gradle.api.tasks.SourceSet +import org.jspecify.annotations.Nullable + +import javax.inject.Inject + +@CompileStatic +class Runs implements Meta { + private final ConventionExtension ext + private boolean hasDependency = false + + @Inject + Runs(ConventionExtension ext) { + this.ext = ext + } + + @Override + Project getProject() { + this.ext.project + } + + void apply(@Nullable String mods, @Nullable File output) { + final project = this.project + final genAllData = this.ext.genAllData + + project.with { + if (!hasDependency && project != project.rootProject) { + dependencies.with { + add('implementation', it.project(':')) // Root project is forge itself + } + hasDependency = true + } + final SourceSet sourceSet = getJava().getSourceSets().named("main").get() + + forgedev.runs.with { + final File existing = sourceSet.getResources().getSrcDirs()[0] + + configureEach { + it.with { + cache.set(project.layout.projectDirectory.dir('runs/cache')) + eclipsePrefix = project.name + + // If we're not forge, we need to get the metadata from the forge project + if (project != project.rootProject) + metadata = project.files(getForgedev().consumeFile('metadata', project.rootProject)) + + var runName = it.name.toLowerCase(Locale.ENGLISH) + + if (runName.contains('client') || runName.contains('data')) { + options.with { + args '--assetsDir', '{assets_root}', '--assetIndex', '{asset_index}' + systemProperty 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll' + } + } + + if (runName.contains('data')) { + options.with(sourceSet).with { + if (mods != null) args('--mod', mods) + if (output != null) args('--output', output) + } + } + + options.with { + getWorkingDir().set(project.layout.projectDirectory.dir("runs/$name")) + getMainClass().set('net.minecraftforge.bootstrap.ForgeBootstrap') + args '--gameDir', '.' + jvmArgs '-Djava.net.preferIPv6Addresses=system', '-XX:+UseCompactObjectHeaders', '-XX:StackShadowPages=32' + + systemProperty 'bsl.debug', 'true' + systemProperty 'terminal.jline', 'true' + systemProperty 'forge.enableGameTest', 'true' + systemProperty 'eventbus.api.strictRuntimeChecks', 'true' + } + } + } + + maybeCreate('client').with { + options.with { + args '--launchTarget', 'forge_dev_client', + '--username', 'Dev', + '--version', project.name, + '--accessToken', '0', + '--userType', 'mojang', + '--versionType', 'release' + } + } + + maybeCreate('server').with { + options.with { + args '--launchTarget', 'forge_dev_server' + } + } + + maybeCreate('gameTestServer').with { + options.with { + args '--launchTarget', 'forge_dev_server_gametest', + '--uniqueWorld' // Unique world is used so that the world regenerates, as well as the world config isn't influenced by other runs + } + } + + maybeCreate('data').with { + options.with { + args '--launchTarget', 'forge_dev_data', + '--all', + '--existing', existing + } + } + + maybeCreate('clientData').with { + options.with { + args '--launchTarget', 'forge_dev_client_data', + '--all', + '--existing', existing + } + } + } + genAllData.configure { + it.dependsOn forgedev.runs.getByName('data').with(sourceSet).run, forgedev.runs.getByName('clientData').with(sourceSet).run + } + } + } + + + void applyTest(@Nullable String mods, @Nullable File output) { + final project = this.project + final genAllData = this.ext.genAllData + + project.with { + final SourceSet sourceSet = getJava().getSourceSets().named("test").get() + forgedev.runs.with { + final File existing = sourceSet.getResources().getSrcDirs()[0] + + configureEach { + it.with { + var runName = it.name.toLowerCase(Locale.ENGLISH) + options.with(sourceSet).with { + systemProperty 'forgedev.enableTestMods', 'true' + } + + if (runName.contains('data')) { + options.with(sourceSet).with { + if (mods != null) args('--mod', mods) + if (output != null) args('--output', output) + args('--existing', existing) + } + } + } + } + } + genAllData.configure { + it.dependsOn forgedev.runs.getByName('data').with(sourceSet).run, forgedev.runs.getByName('clientData').with(sourceSet).run + } + } + } +} diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/VersionsExtension.java b/build-logic/src/main/groovy/net/minecraftforge/forge/build/VersionsExtension.java new file mode 100644 index 0000000000..e8437511f7 --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/VersionsExtension.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build; + +import net.minecraftforge.gitversion.gradle.GitVersionExtension; +import org.gradle.api.Project; +import org.gradle.api.artifacts.VersionCatalog; +import org.gradle.api.artifacts.VersionCatalogsExtension; + +import javax.inject.Inject; + +public abstract class VersionsExtension { + private final VersionCatalog libs; + + public final String java, minecraft, forge, forgeSpec, minecraftNext, mcp, changelogBase; + + @Inject + public VersionsExtension(Project project) { + final var extensions = project.getExtensions(); + final var gitversion = extensions.getByType(GitVersionExtension.class); + libs = extensions.getByType(VersionCatalogsExtension.class).named("bootLibs"); + java = get("java"); + minecraft = get("minecraft"); + minecraftNext = get("minecraft.next"); + mcp = get("mcp"); + changelogBase = get("changelog.base"); + forge = gitversion.of(project.getRootProject()).getVersion(); + forgeSpec = forge.split("\\.")[0]; + project.setVersion(minecraft + '-' + gitversion.getVersion()); + } + + private String get(String name) { + var ver = this.libs.findVersion(name); + if (ver.isEmpty()) + throw new IllegalStateException("No version found for " + name); + return ver.get().toString(); + } +} diff --git a/build-logic/src/main/groovy/net/minecraftforge/forge/build/WriteForgeVersionJson.groovy b/build-logic/src/main/groovy/net/minecraftforge/forge/build/WriteForgeVersionJson.groovy new file mode 100644 index 0000000000..84d1a4bdc3 --- /dev/null +++ b/build-logic/src/main/groovy/net/minecraftforge/forge/build/WriteForgeVersionJson.groovy @@ -0,0 +1,42 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.forge.build + +import groovy.json.JsonBuilder +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction + +import javax.inject.Inject + +@CompileStatic +abstract class WriteForgeVersionJson extends DefaultTask { + abstract @Input Property getForgeVersion() + abstract @Input Property getMinecraftVersion() + abstract @Input Property getMcpVersion() + + abstract @OutputFile RegularFileProperty getOutputFile() + + @Inject + WriteForgeVersionJson() {} + + @TaskAction + @CompileDynamic + void exec() { + var json = new JsonBuilder() + json { + forge this.forgeVersion.get() + mc this.minecraftVersion.get() + mcp this.mcpVersion.get() + } + this.outputFile.asFile.get().text = json.toPrettyString() + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 762fc532af..2cdd674095 100644 --- a/build.gradle +++ b/build.gradle @@ -1,37 +1,20 @@ import org.apache.tools.ant.filters.ReplaceTokens plugins { - id 'java-library' - id 'idea' id 'eclipse' - id 'maven-publish' - alias libs.plugins.licenser alias libs.plugins.versions - alias libs.plugins.gradleutils - alias libs.plugins.gitversion - alias libs.plugins.changelog alias libs.plugins.jarsigner - id 'net.minecraftforge.forgedev' + alias libs.plugins.forgedev id 'net.minecraftforge.forge.build.convention' } gradleutils.displayName = 'Forge' -group = 'net.minecraftforge' description = 'Modifications to Minecraft to enable mod developers.' -// NOTE: See settings.gradle for all the referenceable version variables. -// All subprojects (that apply 'net.minecraftforge.forge.build.convention') will have these available. -println "Version: $version" - -java.toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) - jarSigner.autoDetect('forge') // We have to tell ForgeDev to use the exact versions of tools we ship in the installer fdtools { - configure('mavenizer') { - version = '0.5.22' - } configure('binpatcher') { version = buildLibs.binarypatcher.get().version } @@ -47,18 +30,19 @@ fdtools { forgedev.validatePublish { task { baseBranch = 'upstream/26.1.2' - versionPrefix = minecraftVersion + versionPrefix = versions.minecraft } } */ -final minecraftFiles = forgedev.minecraftFiles(minecraftVersion) +final minecraftFiles = forgedev.minecraftFiles(versions.minecraft) final mcpBase = forgedev.mcpBase { - mcpVersion = "${minecraftVersion}-${project.ext.mcpVersion}" + mcpVersion = "${versions.minecraft}-${versions.mcp}" accessTransformers.from file('src/main/resources/META-INF/accesstransformer.cfg') sideAnnotationStrippers.from file('src/main/resources/forge.sas') } +forgedev.provideFile('metadata', mcpBase.metadata) forgedev.patches { base = mcpBase @@ -81,8 +65,6 @@ sourceSets { } license { - header = file('LICENSE-header.txt') - include 'net/minecraftforge/' exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java' @@ -98,7 +80,6 @@ license { } changelog { - from changelogBase publishAll = false } @@ -120,10 +101,7 @@ configurations { named('api') { extendsFrom(installer) - } - - named('implementation') { - // Inherit vanilla Minecraft's dependencies + // Inherit vanilla Minecraft's dependencies, and let downstream access them extendsFrom(mcpBase.dependencyConfiguration) } } @@ -174,110 +152,13 @@ dependencies { annotationProcessor libs.eventbus.validator } +convention.basicRuns('forge', file('src/main/generated/')) +convention.testRuns('.+', file('src/test/generated/')) + final EXTRA_TXTS = [ - file('LICENSE.txt'), - changelog.task.flatMap(task -> task.outputFile) + file('LICENSE.txt'), + changelog.task.flatMap(task -> task.outputFile) ] -forgedev.runs { - configureEach { - options { - workingDir = layout.projectDirectory.dir("runs/$name") - - mainClass = 'net.minecraftforge.bootstrap.ForgeBootstrap' - args '--gameDir', '.' - jvmArgs '-Djava.net.preferIPv6Addresses=system', '-XX:+UseCompactObjectHeaders', '-XX:StackShadowPages=32' - - systemProperty 'bsl.debug', 'true' - systemProperty 'terminal.jline', 'true' - } - } - create('client') { - options { - systemProperty 'eventbus.api.strictRuntimeChecks', 'true' - systemProperty 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll' - - args '--launchTarget', 'forge_dev_client', - '--username', 'Dev', - '--version', project.name, - '--accessToken', '0', - '--userType', 'mojang', - '--versionType', 'release', - '--assetsDir', '{assets_root}', - '--assetIndex', '{asset_index}' - - with(sourceSets.test) { - systemProperty 'forge.enableGameTest', 'true' - systemProperty 'forgedev.enableTestMods', 'true' - } - } - } - - create('server') { - options { - args '--launchTarget', 'forge_dev_server' - } - } - - create('gameTestServer') { - options { - systemProperty 'forge.enableGameTest', 'true' - args '--launchTarget', 'forge_dev_server_gametest' - args '--uniqueWorld' // Unique world is used so that the world regenerates, as well as the world config isn't influenced by other runs - - with(sourceSets.test) { - systemProperty 'forgedev.enableTestMods', 'true' - } - } - } - - create('data') { - options { - args '--launchTarget', 'forge_dev_data', - '--all', - '--existing', sourceSets.main.resources.srcDirs[0], - '--assetsDir', '{assets_root}', - '--assetIndex', '{asset_index}' - - with(sourceSets.main) { - args '--mod', 'forge', - '--output', rootProject.file('src/main/generated/') - } - - with(sourceSets.test) { - systemProperty 'forge.enableGameTest', 'true' - systemProperty 'forgedev.enableTestMods', 'true' - args '--mod', '.+', - '--existing', sourceSets.test.resources.srcDirs[0], - '--output', rootProject.file('src/test/generated/') - } - } - } - - create('clientData') { - options { - args '--launchTarget', 'forge_dev_client_data', - '--all', - '--existing', sourceSets.main.resources.srcDirs[0], - '--assetsDir', '{assets_root}', - '--assetIndex', '{asset_index}' - - with(sourceSets.main) { - args '--mod', 'forge', - '--output', rootProject.file('src/main/generated/') - } - - with(sourceSets.test) { - systemProperty 'forgedev.enableTestMods', 'true' - args '--mod', '.+', - '--existing', sourceSets.test.resources.srcDirs[0], - '--output', rootProject.file('src/test/generated/') - } - } - } -} -tasks.register('genAllData') { - dependsOn forgedev.runs.data.run, forgedev.runs.data.runTest, forgedev.runs.clientData.run, forgedev.runs.clientData.runTest -} final serverShim = forgedev.shim { config { @@ -304,7 +185,7 @@ final finalizeSpawn = forgedev.methodCallFinder('findFinalizeSpawnTargets') { } forgedev.validateDeprecations(tasks.named('jar', Jar)) { - mcVersion = minecraftVersion + mcVersion = versions.minecraft } forgedev.checks() { @@ -343,24 +224,15 @@ tasks.named('jar', Jar) { manifest { attributes([ - 'Automatic-Module-Name': 'net.minecraftforge.forge' + 'Automatic-Module-Name': 'net.minecraftforge.forge' + ]) + gradleutils.manifestDefaults(it, 'net/minecraftforge/versions/forge/') + gradleutils.manifestDefaults(it, 'net/minecraftforge/versions/mcp/', [ + 'Specification-Title' : 'Minecraft', + 'Specification-Version' : versions.minecraft, + 'Implementation-Title' : 'MCP', + 'Implementation-Version': versions.mcp ]) - attributes([ - 'Specification-Title' : gradleutils.displayName.get(), - 'Specification-Vendor' : gradleutils.vendor.get(), - 'Specification-Version' : gitversion.info.tag, - 'Implementation-Title' : project.group, - 'Implementation-Vendor' : gradleutils.vendor.get(), - 'Implementation-Version': forgeVersion - ], 'net/minecraftforge/versions/forge/') - attributes([ - 'Specification-Title' : 'Minecraft', - 'Specification-Vendor' : gradleutils.vendor.get(), - 'Specification-Version' : minecraftVersion, - 'Implementation-Title' : 'MCP', - 'Implementation-Vendor' : gradleutils.vendor.get(), - 'Implementation-Version': mcpVersion - ], 'net/minecraftforge/versions/mcp/') } jarSigner.sign(it) } @@ -452,7 +324,7 @@ forgedev.userDev { } } -forgedev.userdevCompatibility(minecraftVersion) { +forgedev.userdevCompatibility(versions.minecraft) { clean = mcpBase.classes dirty = tasks.named('jar', Jar) } @@ -490,7 +362,7 @@ forgedev.installer { launcherLibraries configurations.installer - final launcherId = "${minecraftVersion}-${project.name}-${forgeVersion}" + final launcherId = "${versions.minecraft}-${project.name}-${versions.forge}" final installertools = tool(buildLibs.installertools) final binarypatcher = tool(buildLibs.binarypatcher) @@ -533,12 +405,12 @@ forgedev.installer { json { icon = rootProject.file('icon.ico') executable serverShim.jar - minecraft = minecraftVersion + minecraft = versions.minecraft profileVersion = launcherId final projectArtifact = "${project.group}:${project.name}:${project.version}" - data 'MC_UNPACKED', "[net.minecraft:client:${minecraftVersion}]", "[net.minecraft:server:${minecraftVersion}:unpacked]" + data 'MC_UNPACKED', "[net.minecraft:client:${versions.minecraft}]", "[net.minecraft:server:${versions.minecraft}:unpacked]" data 'MC_UNPACKED_SHA', minecraftFiles.client, minecraftFiles.serverExtracted data 'BINPATCH', '/data/client.lzma', '/data/server.lzma' @@ -599,7 +471,7 @@ forgedev.installer { librariesLast = false // Makes libraries be added before args id = launcherId - inheritsFrom = minecraftVersion + inheritsFrom = versions.minecraft mainClass = 'net.minecraftforge.bootstrap.ForgeBootstrap' gameArgs = [ '--launchTarget', 'forge_client' ] jvmArgs = [ '-Djava.net.preferIPv6Addresses=system', '-XX:+UseCompactObjectHeaders', '-XX:StackShadowPages=32' ] @@ -633,12 +505,12 @@ final mdkZip = tasks.register('mdkZip', Zip) { exclude it } filter(ReplaceTokens, tokens: [ - FORGE_VERSION: forgeVersion, + FORGE_VERSION: versions.forge, FORGE_GROUP: project.group, FORGE_NAME: project.name, - MC_VERSION: minecraftVersion, - FORGE_SPEC_VERSION: gitversion.info.tag.split("\\.")[0], - MC_NEXT_VERSION: minecraftNextVersion, + MC_VERSION: versions.minecraft, + FORGE_SPEC_VERSION: versions.forgeSpec, + MC_NEXT_VERSION: versions.minecraftNext, EVENTBUS_VERSION: libs.versions.eventbus.get() ]) rename 'gitignore\\.txt', '.gitignore' @@ -717,8 +589,8 @@ tasks.named('javadoc', Javadoc) { bottom = "Minecraft Forge is an open source modding API for Minecraft: Java Edition, licensed under the Lesser GNU General Public License, version 2.1." windowTitle = "Minecraft Forge API ${version}" - docTitle = "Minecraft Forge API - ${forgeVersion} for Minecraft ${minecraftVersion}" - header = "

${forgeVersion} for Minecraft ${minecraftVersion}
" + docTitle = "Minecraft Forge API - ${versions.forge} for Minecraft ${versions.minecraft}" + header = "
${versions.forge} for Minecraft ${versions.minecraft}
" } doLast { @@ -731,51 +603,31 @@ tasks.named('javadoc', Javadoc) { } */ -publishing { - repositories { - maven gradleutils.publishingForgeMaven - } - - publications.register('mavenJava', MavenPublication) { - changelog.publish(it) - gradleutils.promote(it) - - artifact universalJar - artifact forgedev.installer.jar - artifact mdkZip - artifact forgedev.userDev.jar - artifact sourcesJar - artifact serverShim.jar - - pom { - description = project.description - - gradleutils.pom.addRemoteDetails(pom) - - licenses { - license gradleutils.pom.licenses.LGPLv2_1 - } - } - } +convention.publish { + artifact universalJar + artifact forgedev.installer.jar + artifact mdkZip + artifact forgedev.userDev.jar + artifact sourcesJar + artifact serverShim.jar } - /* // These are debugging tasks that are only used when developing ForgeDevPlugin, to bulk test task's config/caching // region ForgeDev Tests def all = tasks.register('all') {} afterEvaluate { if (gradle.startParameter.taskNames.contains('all')) { - tasks.forEach { task -> // This forces everything to be realized, which is why we have the startParameter check - if (!gradle.startParameter.isTaskGraph() && task.name.startsWith('run')) return + tasks.forEach { task -> // This forces everything to be realized, which is why we have the startParameter check + if (!gradle.startParameter.isTaskGraph() && task.name.startsWith('run')) return if (task.name in [all.name, 'dependencyInsight', 'dependencies', 'dependencyUpdates', 'init', 'buildEnvironment', 'idea', 'eclipse', 'javaToolchains', 'outgoingVariants', 'projects', 'properties', 'resolvableConfigurations', 'tasks', 'updateDaemonJvm', 'generateActionsWorkflow' ]) return if (task.name.startsWith('clean')) return if (task.name == 'checkJarCompatibility') return // This doesn't work in FG6 dev, I think it's cuz we check vs srg names. Will need to look at later - all.configure { dependsOn(task) } - } + all.configure { dependsOn(task) } + } } } */ @@ -789,8 +641,7 @@ tasks.withType(AbstractTestTask).configureEach { [ 'makePatches', 'compileJava', 'checkLicenseMain', 'updateLicenseMain', 'sourcesJar', 'sourcesJarAll' ] .each{ tasks.named(it).configure{ mustRunAfter forgedev.patches.apply }} forgedev.runs.configureEach { - run.configure { dependsOn finalizeSpawn} - runTest.configure { dependsOn finalizeSpawn} + run.configure { dependsOn finalizeSpawn } } // run gradlew dependencyUpdates --no-parallel //noinspection UnnecessaryQualifiedReference diff --git a/fmlcore/build.gradle b/fmlcore/build.gradle index d6adcbbea8..a55c7c1be1 100644 --- a/fmlcore/build.gradle +++ b/fmlcore/build.gradle @@ -1,78 +1,20 @@ plugins { - id 'java-library' - id 'maven-publish' - alias libs.plugins.licenser - alias libs.plugins.gradleutils - alias libs.plugins.gitversion - alias libs.plugins.changelog id 'net.minecraftforge.forge.build.convention' } gradleutils.displayName = 'FML' -final vendor = 'Forge Development LLC' -description = 'Modifications to Minecraft to enable mod developers.' +description = 'Core library used for Forge ModLoader.' dependencies { - compileOnly libs.jetbrains.annotations - api libs.eventbus implementation projects.fmlloader implementation libs.commons.io } -java { - toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) - withSourcesJar() -} +convention.manifest('net/minecraftforge/fml/', [ + 'Automatic-Module-Name': 'net.minecraftforge.fmlcore', + 'FMLModType' : 'LIBRARY' +]) -license { - header = rootProject.file('LICENSE-header.txt') -} -changelog { - from changelogBase -} - -tasks.withType(JavaCompile).configureEach { - options.compilerArgs << '-Xlint:-unchecked' -} - -tasks.named('jar', Jar) { - manifest { - attributes([ - 'Automatic-Module-Name': 'net.minecraftforge.fmlcore', - 'FMLModType' : 'LIBRARY' - ]) - attributes([ - 'Specification-Title' : gradleutils.displayName.get(), - 'Specification-Vendor' : vendor, - 'Specification-Version' : '1', - 'Implementation-Title' : gradleutils.displayName.get(), - 'Implementation-Version': '1.0', - 'Implementation-Vendor' : vendor - ], 'net/minecraftforge/fml/') - } -} - -publishing { - repositories { - maven gradleutils.publishingForgeMaven - } - - publications.register('mavenJava', MavenPublication) { - changelog.publish(it) - gradleutils.promote(it) - - from components.java - - pom { - description = project.description - - gradleutils.pom.addRemoteDetails(pom) - - licenses { - license gradleutils.pom.licenses.LGPLv2_1 - } - } - } -} +convention.publish() diff --git a/fmlearlydisplay/build.gradle b/fmlearlydisplay/build.gradle index a682731335..802115ea73 100644 --- a/fmlearlydisplay/build.gradle +++ b/fmlearlydisplay/build.gradle @@ -1,49 +1,14 @@ import org.gradle.api.plugins.jvm.JvmTestSuite -import org.gradle.internal.os.OperatingSystem plugins { - id 'java-library' id 'jvm-test-suite' - id 'maven-publish' - alias libs.plugins.licenser - alias libs.plugins.gradleutils - alias libs.plugins.gitversion - alias libs.plugins.changelog id 'net.minecraftforge.forge.build.convention' } -switch (OperatingSystem.current()) { - case OperatingSystem.LINUX: - project.ext.lwjglNatives = "natives-linux" - break - case OperatingSystem.MAC_OS: - project.ext.lwjglNatives = "natives-macos" - break - case OperatingSystem.WINDOWS: - project.ext.lwjglNatives = "natives-windows" - break -} - gradleutils.displayName = 'FML Early Display' -final vendor = 'Forge Development LLC' description = 'A pretty looking, but prone to erroring screen displayed during Forge loading.' -java { - toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) - withSourcesJar() -} - -license { - header = rootProject.file('LICENSE-header.txt') -} - -changelog { - from changelogBase -} - dependencies { - compileOnly libs.jetbrains.annotations - implementation projects.fmlloader implementation projects.fmlcore implementation libs.bundles.lwjgl @@ -51,67 +16,19 @@ dependencies { implementation libs.jopt.simple } -// See gradle/gradle#35070 (https://github.com/gradle/gradle/issues/35070) -// We are making the list of providers first BEFORE mapping them to a provider of the resolved objects so that they can be finalized after configuration. -var lwjglTestLibs = [ - dependencies.variantOf(earlyDisplayTestLibs.lwjgl) { classifier lwjglNatives }, - dependencies.variantOf(earlyDisplayTestLibs.lwjgl.opengl) { classifier lwjglNatives }, - dependencies.variantOf(earlyDisplayTestLibs.lwjgl.stb) { classifier lwjglNatives }, - dependencies.variantOf(earlyDisplayTestLibs.lwjgl.sdl) { classifier lwjglNatives } -].with { list -> - provider { list.collect { it.get() } } -} - testing.suites.named('test', JvmTestSuite) { useJUnitJupiter('5.8.2') dependencies { implementation earlyDisplayTestLibs.powermock.core runtimeOnly earlyDisplayLibs.slf4j.jdk14 - runtimeOnly.bundle lwjglTestLibs + runtimeOnly.bundle convention.nativeVariants(earlyDisplayTestLibs.bundles.lwjgl) } } -tasks.withType(JavaCompile).configureEach { - options.compilerArgs << '-Xlint:unchecked' -} +convention.manifest('net/minecraftforge/fml/earlydisplay/', [ + 'Automatic-Module-Name': 'net.minecraftforge.earlydisplay', + 'Forge-Module-Layer' : 'boot' +]) -tasks.named('jar', Jar) { - manifest { - attributes([ - 'Automatic-Module-Name': 'net.minecraftforge.earlydisplay', - 'Forge-Module-Layer' : 'boot' - ]) - attributes([ - 'Specification-Title' : gradleutils.displayName.get(), - 'Specification-Vendor' : vendor, - 'Specification-Version' : '1', - 'Implementation-Title' : gradleutils.displayName.get(), - 'Implementation-Vendor' : vendor, - 'Implementation-Version': '1.0' - ], 'net/minecraftforge/fml/earlydisplay/') - } -} - -publishing { - repositories { - maven gradleutils.publishingForgeMaven - } - - publications.register('mavenJava', MavenPublication) { - changelog.publish(it) - gradleutils.promote(it) - - from components.java - - pom { - description = project.description - - gradleutils.pom.addRemoteDetails(pom) - - licenses { - license gradleutils.pom.licenses.LGPLv2_1 - } - } - } -} \ No newline at end of file +convention.publish() \ No newline at end of file diff --git a/fmlloader/build.gradle b/fmlloader/build.gradle index 21a9112b80..1c17837a2b 100644 --- a/fmlloader/build.gradle +++ b/fmlloader/build.gradle @@ -1,44 +1,17 @@ -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.transform.PackageScope import net.minecraftforge.forgedev.legacy.tasks.JarJarMetadataOptions import org.gradle.api.plugins.jvm.JvmTestSuite -import javax.inject.Inject - plugins { - id 'java-library' id 'jvm-test-suite' - id 'maven-publish' - alias libs.plugins.licenser - alias libs.plugins.gradleutils - alias libs.plugins.gitversion - alias libs.plugins.changelog - alias libs.plugins.apt id 'net.minecraftforge.forge.build.convention' + alias libs.plugins.apt } gradleutils.displayName = 'FMLLoader' -final vendor = 'Forge Development LLC' -description = 'Modifications to Minecraft to enable mod developers.' - -java { - toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) - withSourcesJar() -} - -license { - header = rootProject.file('LICENSE-header.txt') -} - -changelog { - from changelogBase -} +description = 'Mod Locator and manager for Minecraft Forge.' dependencies { - compileOnly libs.jetbrains.annotations - - // TODO [FMLLoader] Figure out a better way to lock transitive dependencies to the explicit versions shipped by the isntaller + // TODO [FMLLoader] Figure out a better way to lock transitive dependencies to the explicit versions shipped by the installer api(libs.bundles.asm ){ transitive = false } // Needed by all the black magic api(libs.forgespi ){ transitive = false } api(libs.mergetool.api ){ transitive = false } @@ -73,86 +46,19 @@ testing.suites.named('test', JvmTestSuite) { } } -tasks.withType(JavaCompile).configureEach { - options.compilerArgs << '-Xlint:unchecked' -} +convention.manifest('net/minecraftforge/fml/loading/', [ + 'Automatic-Module-Name': 'net.minecraftforge.fmlloader', + 'Forge-Module-Layer' : 'boot' +]) -tasks.named('jar', Jar) { - manifest { - attributes([ - 'Automatic-Module-Name': 'net.minecraftforge.fmlloader', - 'Forge-Module-Layer' : 'boot' - ]) - attributes([ - 'Specification-Title' : gradleutils.displayName.get(), - 'Specification-Vendor' : vendor, - 'Specification-Version' : '1', - 'Implementation-Title' : gradleutils.displayName.get(), - 'Implementation-Vendor' : vendor, - 'Implementation-Version': forgeVersion - ], 'net/minecraftforge/fml/loading/') - } -} - -publishing { - repositories { - maven gradleutils.publishingForgeMaven - } - - publications.register('mavenJava', MavenPublication) { - changelog.publish(it) - gradleutils.promote(it) - - from components.java - - pom { - description = project.description - - gradleutils.pom.addRemoteDetails(pom) - - licenses { - license gradleutils.pom.licenses.LGPLv2_1 - } - } - } -} - -// A simple task to write JSON to a file. Using Task#doLast to output files is no longer supported. -// This code may seem verbose, but it's better this way. If more projects need this, we can move it to buildSrc. -@CompileStatic -@PackageScope abstract class WriteForgeVersionJson extends DefaultTask { - abstract @Input Property getForgeVersion() - abstract @Input Property getMinecraftVersion() - abstract @Input Property getMcpVersion() - - abstract @OutputFile RegularFileProperty getOutputFile() - - @Inject - WriteForgeVersionJson() {} - - @TaskAction - @CompileDynamic - void exec() { - var json = new groovy.json.JsonBuilder() - json { - forge this.forgeVersion.get() - mc this.minecraftVersion.get() - mcp this.mcpVersion.get() - } - this.outputFile.asFile.get().text = json.toPrettyString() - } -} - -tasks.register('writeForgeVersionJson', WriteForgeVersionJson) { - forgeVersion = project.forgeVersion - minecraftVersion = project.minecraftVersion - mcpVersion = project.mcpVersion +convention.publish() +final forgeJson = convention.forgeVersionJson { outputFile = file('src/main/resources/forge_version.json') } -tasks.register('jarJarOptionsJson', JarJarMetadataOptions) { - metadataFile = project.file('src/main/resources/jarjar_options.json') +final jarJarJson = tasks.register('jarJarOptionsJson', JarJarMetadataOptions) { + metadataFile = file('src/main/resources/jarjar_options.json') // This is resolved too early by cpw.mods.modlauncher.TransformationServicesHandler.discoverServices(DiscoveryData) But eventually... //add(libs.mixin, 'org/spongepowered/asm/mixin/Mixin.class') add(libs.mixinextras.forge) { @@ -168,11 +74,11 @@ tasks.register('jarJarOptionsJson', JarJarMetadataOptions) { tasks.named('generateResources') { dependsOn( - tasks.named('eclipseJdt'), - tasks.named('eclipseJdtApt'), - tasks.named('eclipseFactorypath'), - tasks.named('writeForgeVersionJson', WriteForgeVersionJson), - tasks.named('jarJarOptionsJson') + tasks.named('eclipseJdt'), + tasks.named('eclipseJdtApt'), + tasks.named('eclipseFactorypath'), + forgeJson, + jarJarJson ) } diff --git a/forge-transformers/build.gradle b/forge-transformers/build.gradle index 145d9ed3e9..60ba0f8f0d 100644 --- a/forge-transformers/build.gradle +++ b/forge-transformers/build.gradle @@ -1,78 +1,21 @@ plugins { - id 'java-library' - id 'maven-publish' - alias libs.plugins.licenser - alias libs.plugins.gradleutils - alias libs.plugins.gitversion - alias libs.plugins.changelog id 'net.minecraftforge.forge.build.convention' } gradleutils.displayName = 'Forge Transformers' -final vendor = 'Forge Development LLC' description = 'Forge-specific transformers unrelated to the FML project.' -java { - toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) - withSourcesJar() -} - -license { - header = rootProject.file('LICENSE-header.txt') -} - -changelog { - from changelogBase -} - dependencies { - compileOnly(libs.jetbrains.annotations) - implementation(libs.bundles.asm ){ transitive = false } // Needed by all the black magic implementation(libs.log4j.api ){ transitive = false } implementation(libs.gson ){ transitive = false } implementation(libs.modlauncher ){ transitive = false } implementation(libs.coremods.api){ transitive = false } - - testCompileOnly(libs.jetbrains.annotations) } -tasks.named('jar', Jar) { - manifest { - attributes([ - 'Automatic-Module-Name': 'net.minecraftforge.forge.transformers', - 'Forge-Module-Layer' : 'boot' - ]) - attributes([ - 'Specification-Title' : gradleutils.displayName.get(), - 'Specification-Vendor' : vendor, - 'Specification-Version' : '1', - 'Implementation-Title' : gradleutils.displayName.get(), - 'Implementation-Vendor' : vendor, - 'Implementation-Version': forgeVersion - ], 'net/minecraftforge/forge/transformers/') - } -} +convention.manifest('net/minecraftforge/forge/transformers/', [ + 'Automatic-Module-Name': 'net.minecraftforge.forge.transformers', + 'Forge-Module-Layer' : 'boot' +]) -publishing { - repositories { - maven gradleutils.publishingForgeMaven - } - - publications.register('mavenJava', MavenPublication) { - changelog.publish(it) - gradleutils.promote(it) - - from components.java - - pom { pom -> - description = project.description - - gradleutils.pom.addRemoteDetails(pom) - - licenses { - license gradleutils.pom.licenses.LGPLv2_1 - } - } - } -} +convention.publish() diff --git a/gradle/buildLibs.versions.toml b/gradle/buildLibs.versions.toml new file mode 100644 index 0000000000..95b5bfaf81 --- /dev/null +++ b/gradle/buildLibs.versions.toml @@ -0,0 +1,7 @@ +# Libraries used solely during the build and publish process. + +[libraries] +binarypatcher = { module = "net.minecraftforge:binarypatcher", version = "1.3.4" } +installer = { module = "net.minecraftforge:installer", version = "2.2.+" } +installertools = { module = "net.minecraftforge:installertools", version = "1.4.6" } +srg2source = { module = "net.minecraftforge:Srg2Source", version = "8.2.0" } diff --git a/gradle/earlyDisplayLibs.versions.toml b/gradle/earlyDisplayLibs.versions.toml new file mode 100644 index 0000000000..76f99dd735 --- /dev/null +++ b/gradle/earlyDisplayLibs.versions.toml @@ -0,0 +1,6 @@ +[versions] +slf4j = "2.0.17" + +[libraries] +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +slf4j-jdk14 = { module = "org.slf4j:slf4j-jdk14", version.ref = "slf4j" } diff --git a/gradle/earlyDisplayTestLibs.versions.toml b/gradle/earlyDisplayTestLibs.versions.toml new file mode 100644 index 0000000000..682b386d96 --- /dev/null +++ b/gradle/earlyDisplayTestLibs.versions.toml @@ -0,0 +1,9 @@ +[libraries] +powermock-core = { module = "org.powermock:powermock-core", version = "2.0.9" } +lwjgl = { module = "org.lwjgl:lwjgl" } +lwjgl-sdl = { module = "org.lwjgl:lwjgl-sdl" } +lwjgl-opengl = { module = "org.lwjgl:lwjgl-opengl" } +lwjgl-stb = { module = "org.lwjgl:lwjgl-stb" } + +[bundles] +lwjgl = ["lwjgl", "lwjgl-sdl", "lwjgl-opengl", "lwjgl-stb"] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000000..9835a69761 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,124 @@ +# Libraries used by Forge and its subprojects. +# Most of these are from Minecraft itself. We should really export those as BOM from Mavenizer + +[plugins] +forgedev = { id = "net.minecraftforge.forgedev", version = "7.0.0-beta.56" } +licenser = { id = "net.minecraftforge.licenser", version = "1.2.0" } +versions = { id = "com.github.ben-manes.versions", version = "0.54.0" } +gradleutils = { id = "net.minecraftforge.gradleutils", version = "3.4.9" } +gitversion = { id = "net.minecraftforge.gitversion", version = "4.0.0" } +changelog = { id = "net.minecraftforge.changelog", version = "3.2.2" } +download = { id = "de.undercouch.download", version = "5.6.0" } +jarsigner = { id = "net.minecraftforge.gradlejarsigner", version = "1.2.1" } +apt = { id = "com.diffplug.eclipse.apt", version = "4.4.1" } + + +[versions] +eventbus = "7.0.6" +mixinextras = "0.5.4" +bootstrap = "2.1.8" +asm = "9.10.1" +jline = "3.25.1" +night-config = "3.7.4" +jarjar = "0.4.2" +log4j = "2.26.0" +lwjgl = "3.4.3" + +[libraries] +# TODO [Forge][Buildscript We should not be needing to manually add transitive dependencies +# If we need to make strict versions for dependencies, we should do so using dependency constraints +forgespi = { module = "net.minecraftforge:forgespi", version = "8.0.0" } # Needs modlauncher +modlauncher = { module = "net.minecraftforge:modlauncher", version = "10.2.6" } # Needs securemodules +securemodules = { module = "net.minecraftforge:securemodules", version = "2.2.24" } # // Needs unsafe +unsafe = { module = "net.minecraftforge:unsafe", version = "0.9.2" } +accesstransformers = { module = "net.minecraftforge:accesstransformers", version = "8.2.17" } +coremods-api = { module = "net.minecraftforge:coremods-api", version = "5.3.1" } +mergetool-api = { module = "net.minecraftforge:mergetool-api", version = "1.0" } +maven-artifact = { module = "org.apache.maven:maven-artifact", version = "3.8.8" } # Used for version comparison + +slf4j-api = { module = "org.slf4j:slf4j-api", version = "2.0.17" } + +# Annotations +jetbrains-annotations = { module = "org.jetbrains:annotations", version = "24.0.1" } # ApiStatus annotations +jspecify = { module = "org.jspecify:jspecify", version = "1.0.1" } # Nullability annotations + +# Eventbus +eventbus = { module = "net.minecraftforge:eventbus", version.ref = "eventbus" } +eventbus-validator = { module = "net.minecraftforge:eventbus-validator", version.ref = "eventbus" } + +# Bootstrap - Converting the process from normal loader into JPMS land +bootstrap = { module = "net.minecraftforge:bootstrap", version.ref = "bootstrap" } +bootstrap-api = { module = "net.minecraftforge:bootstrap-api", version.ref = "bootstrap" } +bootstrap-dev = { module = "net.minecraftforge:bootstrap-dev", version.ref = "bootstrap" } +bootstrap-shim = { module = "net.minecraftforge:bootstrap-shim", version.ref = "bootstrap" } + +# ReadOnlyInMemoryFileSystem - Used for JarInJar extraction at runtime +roimfs = { module = "net.minecraftforge:roimfs", version = "1.0.0" } +# Google's InMemory File System. Used by ForgeDev Tests for now, but could be useful for a lot of things. +# ROIMFS is faster if you need read only +jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" } + +# Mixin +mixin = { module = "org.spongepowered:mixin", version = "0.8.7" } +mixinextras-forge = { module = "io.github.llamalad7:mixinextras-forge", version.ref = "mixinextras" } +mixinextras-common = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinextras" } + +# ASM it's used for so many of our hacks +asm = { module = "org.ow2.asm:asm", version.ref = "asm" } +asm-tree = { module = "org.ow2.asm:asm-tree", version.ref = "asm" } +asm-util = { module = "org.ow2.asm:asm-util", version.ref = "asm" } +asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" } +asm-analysis = { module = "org.ow2.asm:asm-analysis", version.ref = "asm" } + +# Terminal Console Appender. essentially make pretty colors in the console, but it's been a PITA +terminalconsoleappender = { module = "net.minecrell:terminalconsoleappender", version = "1.2.0" } +jline-reader = { module = "org.jline:jline-reader", version.ref = "jline" } +jline-terminal = { module = "org.jline:jline-terminal", version.ref = "jline" } +jline-terminal-jna = { module = "org.jline:jline-terminal-jna", version.ref = "jline" } + +# The core of our configuration system, it has many flaws, but it works for the most part +night-config-toml = { module = "com.electronwill.night-config:toml", version.ref = "night-config" } +night-config-core = { module = "com.electronwill.night-config:core", version.ref = "night-config" } + +# Jar In Jar FileSystem +jarjar-fs = { module = "net.minecraftforge:JarJarFileSystems", version.ref = "jarjar" } +jarjar-meta = { module = "net.minecraftforge:JarJarMetadata", version.ref = "jarjar" } +jarjar-selector = { module = "net.minecraftforge:JarJarSelector", version.ref = "jarjar" } + +# These are libraries shipped by the MC launcher, try and keep them in sync with the manifest +# but honestly if we don't it just means we ship them as normal libraries by adding them to the installer config in the forge project +gson = { module = "com.google.code.gson:gson", version = "2.14.0" } +guava = { module = "com.google.guava:guava", version = "33.6.0-jre" } +failureaccess = { module = "com.google.guava:failureaccess", version = "1.0.3" } +apache-commons = { module = "org.apache.commons:commons-lang3", version = "3.20.0" } +mojang-logging = { module = "com.mojang:logging", version = "1.7.12" } +jopt-simple = { module = "net.sf.jopt-simple:jopt-simple", version = "5.0.4" } +commons-io = { module = "commons-io:commons-io", version = "2.20.0" } + + +log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" } +log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } + +lwjgl = { module = "org.lwjgl:lwjgl", version.ref = "lwjgl" } +lwjgl-sdl = { module = "org.lwjgl:lwjgl-sdl", version.ref = "lwjgl" } +lwjgl-opengl = { module = "org.lwjgl:lwjgl-opengl", version.ref = "lwjgl" } +lwjgl-stb = { module = "org.lwjgl:lwjgl-stb", version.ref = "lwjgl" } +lwjgl-tinyfd = { module = "org.lwjgl:lwjgl-tinyfd", version.ref = "lwjgl" } + +[bundles] +# Google's InMemory File System. Used by ForgeDev Tests for now, but could be useful for a lot of things. +jimfs = ["guava", "failureaccess"] + +# ASM it's used for so many of our hacks +asm = ["asm", "asm-tree", "asm-util", "asm-commons", "asm-analysis"] + +# Pretty colors in the server console +terminalconsoleappender = ["terminalconsoleappender", "jline-reader", "jline-terminal", "jline-terminal-jna"] + +# Utility for reading and writing the TOML file format +night-config = ["night-config-toml", "night-config-core"] + +# Bundeling dependencies in a single archive +jarjar = ["jarjar-fs", "jarjar-selector", "jarjar-meta"] +log4j = ["log4j-api", "log4j-core"] +lwjgl = ["lwjgl", "lwjgl-sdl", "lwjgl-opengl", "lwjgl-stb", "lwjgl-tinyfd"] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d17295f1de7c53e24fdf13ad755c379..eddabd2eef8d94a5437d6168ff9c87a78ff725b3 100644 GIT binary patch delta 39228 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 - project.pluginManager.withPlugin('net.minecraftforge.forge.build.convention') { - // NOTE: We are defining these variables in here so that the projects can stay isolated, increasing build time. - // See minecraft.versions.toml for the versions where you can change these values. - //@formatter:off - project.ext.javaVersion = project.gradleutils.unpack(project.bootLibs.versions.java) - project.ext.minecraftVersion = project.gradleutils.unpack(project.bootLibs.versions.minecraft) - project.version = project.gitversion.getMCTagOffsetBranch(project.ext.minecraftVersion) - project.ext.forgeVersion = project.version.substring(project.ext.minecraftVersion.length() + 1) - project.ext.minecraftNextVersion = project.gradleutils.unpack(project.bootLibs.versions.minecraft.next) - project.ext.mcpVersion = project.gradleutils.unpack(project.bootLibs.versions.mcp) - project.ext.changelogBase = project.gradleutils.unpack(project.bootLibs.versions.changelog.base) - //@formatter:on - } - - // NOTE: We are adding dependencies to projects instead of through settings, so we don't have to apply forgedev in settings. - // Applying forgedev in settings will break IDE linting support, which makes it very hard to work with. - // We can reconsider this if/when switching to Kotlin DSL, or if JetBrains gets their shit together. - project.repositories { - // Libraries has to be before maven central because Mojang hosts a classifer that central doesn't (org.lwjgl:lwjgl-freetype:3.3.3:natives-macos-patch) - maven { url = 'https://libraries.minecraft.net/' } - mavenCentral() - - project.pluginManager.withPlugin('net.minecraftforge.gradleutils') { - maven project.gradleutils.forgeMaven - } - - project.pluginManager.withPlugin('net.minecraftforge.forgedev') { - maven project.forgedev.mavenizer - } - - mavenLocal() - } -} - dependencyResolutionManagement.versionCatalogs { register('bootLibs') { - description = 'Important version numbers that are externally declared for easy modification.' - - // Contains Java, Minecraft, and MCP versions + description = 'Java, Minecraft, and MCP versions' from(files('minecraft.versions.toml')) } register('buildLibs') { description = 'Libraries used solely during the build and publish process.' - - library 'binarypatcher', 'net.minecraftforge', 'binarypatcher' version '1.3.4' - library 'installer', 'net.minecraftforge', 'installer' version '2.2.+' - library 'installertools', 'net.minecraftforge', 'installertools' version '1.4.6' - library 'srg2source', 'net.minecraftforge', 'Srg2Source' version '8.2.0' + from(files('gradle/buildLibs.versions.toml')) } - //@formatter:off register('libs') { description = 'Libraries used by Forge and its subprojects.' - - plugin 'licenser', 'net.minecraftforge.licenser' version '1.2.0' - plugin 'versions', 'com.github.ben-manes.versions' version '0.54.0' - plugin 'gradleutils', 'net.minecraftforge.gradleutils' version '3.4.5' - plugin 'gitversion', 'net.minecraftforge.gitversion' version '3.1.7' - plugin 'changelog', 'net.minecraftforge.changelog' version '3.2.2' - plugin 'download', 'de.undercouch.download' version '5.6.0' - plugin 'jarsigner', 'net.minecraftforge.gradlejarsigner' version '1.2.1' - plugin 'apt', 'com.diffplug.eclipse.apt' version '4.4.1' - - // TODO [Forge][Buildscript We should not be needing to manually add transitive dependencies - // If we need to make strict versions for dependencies, we should do so using dependency constraints - library 'forgespi', 'net.minecraftforge', 'forgespi' version '8.0.0' // Needs modlauncher - library 'modlauncher', 'net.minecraftforge', 'modlauncher' version '10.2.6' // Needs securemodules - library 'securemodules', 'net.minecraftforge', 'securemodules' version '2.2.24' // Needs unsafe - library 'unsafe', 'net.minecraftforge', 'unsafe' version '0.9.2' - library 'accesstransformers', 'net.minecraftforge', 'accesstransformers' version '8.2.17' - library 'coremods-api', 'net.minecraftforge', 'coremods-api' version '5.3.1' - version 'eventbus', '7.0.6' - library 'eventbus', 'net.minecraftforge', 'eventbus' versionRef 'eventbus' - library 'eventbus-validator', 'net.minecraftforge', 'eventbus-validator' versionRef 'eventbus' - library 'mergetool-api', 'net.minecraftforge', 'mergetool-api' version '1.0' - - library 'roimfs', 'net.minecraftforge', 'roimfs' version '1.0.0' // ReadOnlyInMemoryFileSystem - Used for JarInJar extraction at runtime - library 'mixin', 'org.spongepowered', 'mixin' version '0.8.7' - version 'mixinextras', '0.5.4' - library 'mixinextras-forge', 'io.github.llamalad7', 'mixinextras-forge' versionRef 'mixinextras' - library 'mixinextras-common', 'io.github.llamalad7', 'mixinextras-common' versionRef 'mixinextras' - library 'jetbrains-annotations', 'org.jetbrains', 'annotations' version '24.0.1' // for ApiStatus annotations - library 'jspecify', 'org.jspecify', 'jspecify' version '1.0.1' // for nullability annotations - library 'slf4j-api', 'org.slf4j', 'slf4j-api' version '2.0.17' - library 'maven-artifact', 'org.apache.maven', 'maven-artifact' version '3.8.8' - - // Google's InMemory File System. Used by ForgeDev Tests for now, but could be useful for a lot of things. - library 'jimfs', 'com.google.jimfs:jimfs:1.3.0' - bundle 'jimfs', ['guava', 'failureaccess'] - - version 'bootstrap', '2.1.8' - library 'bootstrap', 'net.minecraftforge', 'bootstrap' versionRef 'bootstrap' // Needs modlauncher - library 'bootstrap-api', 'net.minecraftforge', 'bootstrap-api' versionRef 'bootstrap' - library 'bootstrap-dev', 'net.minecraftforge', 'bootstrap-dev' versionRef 'bootstrap' - library 'bootstrap-shim', 'net.minecraftforge', 'bootstrap-shim' versionRef 'bootstrap' - - // ASM it's used for so many of our hacks - version 'asm', '9.10.1' - library 'asm', 'org.ow2.asm', 'asm' versionRef 'asm' - library 'asm-tree', 'org.ow2.asm', 'asm-tree' versionRef 'asm' - library 'asm-util', 'org.ow2.asm', 'asm-util' versionRef 'asm' - library 'asm-commons', 'org.ow2.asm', 'asm-commons' versionRef 'asm' - library 'asm-analysis', 'org.ow2.asm', 'asm-analysis' versionRef 'asm' - bundle 'asm', ['asm', 'asm-tree', 'asm-util', 'asm-commons', 'asm-analysis'] - - // Terminal Console Appender. essentially make pretty colors in the console, but it's been a PITA - library 'terminalconsoleappender', 'net.minecrell', 'terminalconsoleappender' version '1.2.0' - version 'jline', '3.25.1' - library 'jline-reader', 'org.jline', 'jline-reader' versionRef 'jline' - library 'jline-terminal', 'org.jline', 'jline-terminal' versionRef 'jline' - library 'jline-terminal-jna', 'org.jline', 'jline-terminal-jna' versionRef 'jline' // Colors and tab completeion - bundle 'terminalconsoleappender', ['terminalconsoleappender', 'jline-reader', 'jline-terminal', 'jline-terminal-jna'] - - // The core of our configuration system, it has many flaws, but it works for the most part - version 'night-config', '3.7.4' - library 'night-config-toml', 'com.electronwill.night-config', 'toml' versionRef 'night-config' - library 'night-config-core', 'com.electronwill.night-config', 'core' versionRef 'night-config' - bundle 'night-config', ['night-config-toml', 'night-config-core'] - - // Jar in Jar FileSystem - version 'jarjar', '0.4.2' - library 'jarjar-fs', 'net.minecraftforge', 'JarJarFileSystems' versionRef 'jarjar' - library 'jarjar-meta', 'net.minecraftforge', 'JarJarMetadata' versionRef 'jarjar' - library 'jarjar-selector', 'net.minecraftforge', 'JarJarSelector' versionRef 'jarjar' - bundle 'jarjar', ['jarjar-fs', 'jarjar-selector', 'jarjar-meta'] - - // These are libraries shipped by the MC launcher, try and keep them in sync with the manifest - // but honestly if we don't it just means we ship them as normal libraries by adding them to the installer config in the forge project - library 'gson', 'com.google.code.gson', 'gson' version '2.14.0' - library 'guava', 'com.google.guava', 'guava' version '33.6.0-jre' - library 'failureaccess', 'com.google.guava', 'failureaccess' version '1.0.3' - - version 'log4j', '2.26.0' - library 'log4j-api', 'org.apache.logging.log4j', 'log4j-api' versionRef 'log4j' - library 'log4j-core', 'org.apache.logging.log4j', 'log4j-core' versionRef 'log4j' - bundle 'log4j', ['log4j-api', 'log4j-core'] - - library 'apache-commons', 'org.apache.commons', 'commons-lang3' version '3.20.0' - library 'mojang-logging', 'com.mojang', 'logging' version '1.7.12' - library 'jopt-simple', 'net.sf.jopt-simple', 'jopt-simple' version '5.0.4' - library 'commons-io', 'commons-io', 'commons-io' version '2.20.0' - - version 'lwjgl', '3.4.3' - library 'lwjgl', 'org.lwjgl', 'lwjgl' versionRef 'lwjgl' - library 'lwjgl-opengl', 'org.lwjgl', 'lwjgl-opengl' versionRef 'lwjgl' - library 'lwjgl-stb', 'org.lwjgl', 'lwjgl-stb' versionRef 'lwjgl' - library 'lwjgl-sdl', 'org.lwjgl', 'lwjgl-sdl' versionRef 'lwjgl' - library 'lwjgl-tinyfd', 'org.lwjgl', 'lwjgl-tinyfd' versionRef 'lwjgl' - bundle 'lwjgl', ['lwjgl', 'lwjgl-opengl', 'lwjgl-stb', 'lwjgl-sdl', 'lwjgl-tinyfd'] } register('earlyDisplayLibs') { - version 'slf4j', '2.0.17' - library 'slf4j-api', 'org.slf4j', 'slf4j-api' versionRef 'slf4j' - library 'slf4j-jdk14', 'org.slf4j', 'slf4j-jdk14' versionRef 'slf4j' + from(files('gradle/earlyDisplayLibs.versions.toml')) } register('earlyDisplayTestLibs') { - library 'powermock-core', 'org.powermock', 'powermock-core' version '2.0.9' - - library 'lwjgl', 'org.lwjgl', 'lwjgl' withoutVersion() - library 'lwjgl-opengl', 'org.lwjgl', 'lwjgl-opengl' withoutVersion() - library 'lwjgl-stb', 'org.lwjgl', 'lwjgl-stb' withoutVersion() - library 'lwjgl-sdl', 'org.lwjgl', 'lwjgl-sdl' withoutVersion() - bundle 'lwjgl', ['lwjgl', 'lwjgl-opengl', 'lwjgl-stb', 'lwjgl-sdl'] + from(files('gradle/earlyDisplayTestLibs.versions.toml')) } - //@formatter:on }