diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index ea7d5307b8..f8af9a776f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -2,7 +2,7 @@ name: Publish
on:
push:
- branches: [ '26.2' ]
+ branches: [ '26.1' ]
permissions:
contents: read
diff --git a/.gitignore b/.gitignore
index c134175e62..4dcbfe411a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,3 @@
-#forgedev dev if the folder exists in here
-forgedev
-
#eclipse
**/bin
**/.settings
@@ -25,12 +22,10 @@ forgedev
/*/build
/*/.gradle
-# Minecraft
-/run
-/*.launch
-
# Projects repo, either ignore it, or ignore patches.
-src/minecraft
+/projects/mcp/
+/projects/clean/
+/projects/forge/
#occupational hazards
/projects/**/build/
@@ -38,7 +33,6 @@ src/minecraft
/projects/**/run/
/projects/**/*.launch
/repo/
-/rejects-*/
src/*/generated/**/.cache/
# Generated by gradle every import
@@ -53,8 +47,3 @@ src/*/generated/**/.cache/
/*/.factorypath
/*/.apt_generated/
/fmlcore/logs/
-/lib/
-/_actual/
-/runs/
-/forge.ipr
-/forge.iws
diff --git a/LICENSE.txt b/LICENSE.txt
index 51c22dd7db..249debe26b 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -3,7 +3,7 @@ parts herein are licensed under the terms of the LGPL 2.1 found
here http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt and
copied below.
-Homepage: https://minecraftforge.net/
+Homepage: http://minecraftforge.net/
https://github.com/MinecraftForge/MinecraftForge
diff --git a/build.gradle b/build.gradle
index 76f7de0ad6..34c55fa107 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,795 +1,57 @@
-import org.apache.tools.ant.filters.ReplaceTokens
+import net.minecraftforge.forge.tasks.*
+import net.minecraftforge.gradleutils.PomUtils
plugins {
- id 'java-library'
- id 'idea'
+ id 'net.minecraftforge.licenser' version '1.0.1'
+ id 'com.github.ben-manes.versions' version '0.46.0'
+ id 'net.minecraftforge.gradleutils' version '[2.6.4,2.7)'
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'
- id 'net.minecraftforge.forge.build.convention'
+ id 'de.undercouch.download' version '5.4.0'
+ id 'net.minecraftforge.gradle.patcher' version '[6.0.51,6.2)' apply false
+ id 'net.minecraftforge.gradle.mcp' version '[6.0.51,6.2)' apply false
+ id 'net.minecraftforge.gradlejarsigner' version '1.0.4'
+ id 'org.barfuin.gradle.taskinfo' version '3.0.1'
}
-gradleutils.displayName = 'Forge'
-group = 'net.minecraftforge'
-description = 'Modifications to Minecraft to enable mod developers.'
+Util.init() //Init all our extension methods!
-// 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('binpatcher') {
- version = buildLibs.binarypatcher.get().version
- }
- configure('installertools') {
- version = buildLibs.installertools.get().version
- }
- configure('jarcompatibilitychecker') {
- javaLauncher = javaToolchains.launcherFor(java.toolchain)
- }
-}
-
-/* This is used for debugging, comparing all published artifacts against actual production
-forgedev.validatePublish {
- task {
- baseBranch = 'upstream/26.1.2'
- versionPrefix = minecraftVersion
- }
-}
-*/
-
-final minecraftFiles = forgedev.minecraftFiles(minecraftVersion)
-
-final mcpBase = forgedev.mcpBase {
- mcpVersion = "${minecraftVersion}-${project.ext.mcpVersion}"
- accessTransformers.from file('src/main/resources/META-INF/accesstransformer.cfg')
- sideAnnotationStrippers.from file('src/main/resources/forge.sas')
-}
-
-forgedev.patches {
- base = mcpBase
- patches = file('patches/minecraft')
- patched = file('src/minecraft/java')
- sourceSets.main.java.srcDir patched
-}
-
-tasks.register('setup') {
- dependsOn forgedev.patches.apply
-}
-
-sourceSets {
- named('main') {
- resources.srcDir 'src/main/generated'
- }
- named('test') {
- resources.srcDir 'src/test/generated'
- }
-}
-
-license {
- header = file('LICENSE-header.txt')
-
- include 'net/minecraftforge/'
- exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java'
-
- tasks.tap {
- register('main') {
- files.from files('src/main/java')
- }
-
- register('test') {
- files.from files('src/test/java')
- }
- }
+ext {
+ VERSION = gitversion.getMCTagOffsetBranch(MC_VERSION)
+ FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
}
changelog {
- from changelogBase
- publishAll = false
+ from '47.999'
}
-// TODO [ForgeDev] Support compileOnlyApi, runtimeOnly, and a consumable annotation processor configuration
-configurations {
- // Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
- register('bootstrap') {
- transitive = false
- canBeDeclared = true
- canBeResolved = true
- }
-
- register('installer') {
- transitive = false
- canBeDeclared = true
- canBeResolved = true
- extendsFrom(bootstrap)
- }
-
- named('api') {
- extendsFrom(installer)
- }
-
- named('implementation') {
- // Inherit vanilla Minecraft's dependencies
- extendsFrom(mcpBase.dependencyConfiguration)
- }
+tasks.register('setup') {
+ dependsOn ':forge:extractMapped'
+ if (findProject(':clean'))
+ dependsOn ':clean:extractMapped'
}
-dependencies {
- // These need to actually be on the classpath at the start. This is only used for the server shim jar.
- // And this is only needed because custom file systems are REQUIRED to be on the boot classloader.
- // This has ASM/BootStrap/Unsafe all because I haven't gotten around to moving UnionFileSystem out to its own project.
- bootstrap libs.jarjar.fs // JarInJar file system
- bootstrap libs.roimfs // JarInJar File System - FileSystems need to be on boot loader.
- bootstrap libs.bundles.jimfs // In memory file system used for ForgeDev launches
- bootstrap libs.securemodules // Has Union file system in it
- bootstrap libs.unsafe // Needed by securemodules
- bootstrap libs.bundles.asm // Needed by securemodules
-
- implementation libs.jopt.simple
-
- installer libs.bootstrap
- installer libs.bootstrap.api // Needed by securemodules
- installer libs.accesstransformers
- installer libs.eventbus
- installer libs.jspecify // Dep of EventBus
- installer libs.forgespi
- installer libs.coremods.api
- installer libs.modlauncher
- installer libs.mergetool.api
- installer libs.bundles.night.config
- installer libs.maven.artifact
- installer libs.bundles.terminalconsoleappender
- installer libs.mixin
- installer libs.mixinextras.forge
- installer libs.bundles.jarjar
- installer libs.roimfs
-
- installer projects.fmlcore
- installer projects.fmlloader
- installer projects.fmlearlydisplay
- installer projects.javafmllanguage
- installer projects.lowcodelanguage
- installer projects.mclanguage
- installer projects.forgeTransformers
-
- runtimeOnly files(mcpBase.extra)
-
- runtimeOnly libs.bootstrap
- runtimeOnly libs.bootstrap.dev
-
- annotationProcessor libs.eventbus.validator
+tasks.register('doChecks') {
+ dependsOn ':forge:checkJarCompatibility'
+ dependsOn ':forge:publish'
}
-final EXTRA_TXTS = [
- 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'
-
- systemProperty 'bsl.debug', 'true'
- systemProperty 'terminal.jline', 'true'
- with(sourceSets.test) {
- systemProperty 'forge.enableGameTest', 'true'
- systemProperty 'forgedev.enableTestMods', 'true'
- }
- }
+project(':mcp') {
+ apply plugin: 'net.minecraftforge.gradle.mcp'
+ mcp {
+ config MC_VERSION + '-' + MCP_VERSION
+ pipeline = 'joined'
}
-
- 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}'
- }
- }
-
- create('server') {
- options {
- args '--launchTarget', 'forge_dev_server'
- }
- }
-
- create('gameTestServer') {
- options {
- 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
- }
- }
-
- 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) {
- args '--mod', '.+',
- '--existing', sourceSets.test.resources.srcDirs[0],
- '--output', rootProject.file('src/test/generated/')
- }
- }
- }
-
- create('clientData') {
- options {
- args '--all',
- '--existing', sourceSets.main.resources.srcDirs[0],
- '--assetsDir', '{assets_root}',
- '--assetIndex', '{asset_index}'
-
- with(sourceSets.main) {
- args '--launchTarget', 'forge_dev_client_data',
- '--mod', 'forge',
- '--output', rootProject.file('src/main/generated/'),
- '--mod', 'forge'
- }
-
- with(sourceSets.test) {
- args '--launchTarget', 'forge_dev',
- '--launchEntry', 'minecraft/net.minecraft.client.data.Main',
- '--launchData',
- '--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 {
- mainClass = 'net.minecraftforge.bootstrap.ForgeBootstrap'
- args = ['--launchTarget', 'forge_server']
- }
- classpath {
- libraries configurations.installer
- library tasks.named('universalJar', Jar)
- library forgedev.binaryPatches('server').apply, 'server'
- serverBundle.fileProvider(minecraftFiles.server)
- }
- bootstrapClasspath(configurations.bootstrap)
- jar {
- jarSigner.sign(it)
- }
-}
-
-final finalizeSpawn = forgedev.methodCallFinder('findFinalizeSpawnTargets') {
- jar.fileProvider(mcpBase.classes)
- output = rootProject.file('forge-transformers/src/main/resources/coremods/finalize_spawn_targets.json')
- blacklist 'net/minecraft/world/level/BaseSpawner' // Ignore this class as we special case it.
- invokeVirtual('finalizeSpawn', '(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;')
-}
-
-forgedev.validateDeprecations(tasks.named('jar', Jar)) {
- mcVersion = minecraftVersion
-}
-
-forgedev.checks() {
- base = mcpBase
- ats {}
- sas {}
- execs {}
-
- patches {
- dependsOn forgedev.patches.make
- patchDir = forgedev.patches.patches
- patchesWithS2SArtifact = [
- 'minecraft/net/minecraft/client/renderer/ViewArea.java.patch',
- 'minecraft/net/minecraft/data/models/blockstates/Variant.java.patch',
- ]
- }
-
- fix {
- dependsOn finalizeSpawn
- }
-
- forgedev.patches.make.configure {
- finalizedBy forgedev.checks.patches.fix
- }
-}
-
-final crowdin = forgedev.crowdin // Create the crowdin tasks
-tasks.named('jar', Jar) {
- from(EXTRA_TXTS)
- duplicatesStrategy = DuplicatesStrategy.EXCLUDE
- exclude '.cache'
-
- from(zipTree(crowdin.flatMap { it.output } )) {
- include 'assets/forge/lang/*.json'
- }
-
- manifest {
- attributes([
- 'Automatic-Module-Name': 'net.minecraftforge.forge'
- ])
- 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)
-}
-
-final universalJar = tasks.register('universalJar', Jar) {
- from (zipTree(tasks.named('jar', Jar).flatMap { it.archiveFile } )) {
- exclude(forgedev.filterVanilla(mcpBase.classes))
- }
- manifest = tasks.named('jar', Jar).get().manifest
- archiveClassifier = 'universal'
- jarSigner.sign(it)
-}
-
-final sourcesJarAll = tasks.register('sourcesJarAll', Jar) {
- archiveClassifier = 'sources-all'
- from(sourceSets.main.allJava.srcDirs)
-}
-
-// Our sources, plus the patches we do to Vanilla Minecraft
-final sourcesJar = tasks.register('sourcesJar', Jar) {
- archiveClassifier = 'sources'
- from(sourceSets.main.allJava.srcDirs - forgedev.patches.patched.asFile.get())
- mustRunAfter(forgedev.patches.make)
- from(forgedev.patches.patches) {
- into 'patches/'
- }
-}
-
-forgedev.userDev {
- base(mcpBase)
-
- config {
- universal universalJar
- sources sourcesJar
- addLibraries(configurations.installer)
- // TODO [ForgeDev][UserDev] Split API/Runtime elements in userdev config
- // so we don't gotta keep making exceptions for MixinExtras
- addCompileDependency(libs.mixinextras.common)
- addAnnotationProcessorDependency(libs.mixinextras.common)
-
- // TODO [ForgeDev] Consolidate Patcher + UserDev Config runs in a sane way
- runs {
- configureEach {
- parents = []
- main = 'net.minecraftforge.bootstrap.ForgeBootstrap'
- args '--gameDir', '.'
- jvmArgs '-Djava.net.preferIPv6Addresses=system', '-XX:+UseCompactObjectHeaders'
- client = it.name.containsIgnoreCase('client')
- environment 'MCP_MAPPINGS', '{mcp_mappings}'
- }
-
- register('clientData') {
- args '--launchTarget', "forge_userdev_client_data"
- args '--assetIndex', '{asset_index}'
- args '--assetsDir', '{assets_root}'
- }
-
- register('client') {
- property 'forge.enableGameTest', 'true'
- args '--launchTarget', "forge_userdev_client"
- args '--version', 'MOD_DEV'
- args '--assetIndex', '{asset_index}'
- args '--assetsDir', '{assets_root}'
- }
-
- register('server') {
- property 'forge.enableGameTest', 'true'
- args '--launchTarget', "forge_userdev_server"
- }
-
- register('gameTestServer') {
- args '--launchTarget', "forge_userdev_server_gametest"
- }
-
- register('data') {
- args '--launchTarget', "forge_userdev_data"
- args '--assetIndex', '{asset_index}'
- args '--assetsDir', '{assets_root}'
- }
- }
- }
- patches {
- modified.setFrom(sourcesJarAll.flatMap { it.archiveFile })
- }
- binaryPatches {
- mustRunAfter(forgedev.patches.make)
- patches.setFrom(forgedev.patches.patches)
- dirty.setFrom(tasks.named('jar', Jar).flatMap { it.archiveFile })
- }
-}
-
-forgedev.userdevCompatibility(minecraftVersion) {
- clean = mcpBase.classes
- dirty = tasks.named('jar', Jar)
-}
-
-// region Installer tasks, Not needed when we simplify the installer/remove obf
-final clientBinPatches = forgedev.binaryPatches('client') {
- clean = minecraftFiles.client
- // Workaround for 3rd party launcher issues, marker needed to locate MC, store needed to fix zlib-ng issues
- apply {
- store = true
- marker = '.forge_patched_minecraft'
- }
-}
-final serverBinPatches = forgedev.binaryPatches('server') {
- clean = minecraftFiles.serverExtracted
- apply { store = true }
-}
-// endregion
-
-forgedev.installer {
- dev = !forgedev.ci
- offline = false
- baseVersion = buildLibs.installer.get().version.toString()
-
- // Add extra libraries
- pack serverShim.jar // The Server executable jar IS needed to be packed, as the installer would need a spec bump in order to download it
- pack universalJar // I don't think this is strictly needed to be packed anymore, will need to double check later
-
- launcherLibrary universalJar
- // We configure the launcher here to keep the order for easier diff, after publishing, move this to the LauncherJson configuration below
- launcherJson {
- // We create this during install, so it's not downloadable
- generated(clientBinPatches.apply, 'client')
- }
-
- launcherLibraries configurations.installer
-
- final launcherId = "${minecraftVersion}-${project.name}-${forgeVersion}"
- final installertools = tool(buildLibs.installertools)
- final binarypatcher = tool(buildLibs.binarypatcher)
-
- jar {
- from(EXTRA_TXTS)
- from(rootProject.file('/forge_installer_logo.png')) {
- rename { 'big_logo.png' }
- }
- from(clientBinPatches.create.flatMap { t -> t.output }) {
- rename { 'data/client.lzma' }
- }
- from(serverBinPatches.create.flatMap { t -> t.output }) {
- rename { 'data/server.lzma' }
- }
-
- final argsFile = rootProject.file('server_files/args.txt')
- final tokens = [tokens: [
- SHIM_JAR_FILE: serverShim.jar.get().archiveFileName.get(),
- MAVEN_PATH: forgedev.mavenArtifact.directory
- ]]
- from(argsFile) {
- filter(tokens, ReplaceTokens)
- into 'data'
- rename { 'unix_args.txt' }
- }
- from(argsFile) {
- filter(tokens, ReplaceTokens)
- into 'data'
- rename { 'win_args.txt' }
- }
-
- from(rootProject.file('server_files')) {
- filter(tokens, ReplaceTokens)
- into 'data'
- exclude 'args.txt'
- }
-
- jarSigner.sign(it)
- }
- json {
- icon = rootProject.file('icon.ico')
- executable serverShim.jar
- minecraft = minecraftVersion
- 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_SHA', minecraftFiles.client, minecraftFiles.serverExtracted
-
- data 'BINPATCH', '/data/client.lzma', '/data/server.lzma'
- data 'PATCHED', "[$projectArtifact:client]", "[$projectArtifact:server]"
- data 'PATCHED_SHA', clientBinPatches.apply.flatMap { it.output }, serverBinPatches.apply.flatMap { it.output }
-
- steps = [
- extract(installertools) {
- side = 'server'
- archive '{INSTALLER}'
- extract 'data/README.txt', '{ROOT}/README.txt'
- extract 'data/run.sh', '{ROOT}/run.sh'
- executable '{ROOT}/run.sh'
- extract 'data/run.bat', '{ROOT}/run.bat'
- optional 'data/user_jvm_args.txt', '{ROOT}/user_jvm_args.txt'
- extract 'data/unix_args.txt', "{ROOT}/libraries/${forgedev.mavenArtifact.directory}/unix_args.txt"
- extract 'data/win_args.txt', "{ROOT}/libraries/${forgedev.mavenArtifact.directory}/win_args.txt"
- },
- extractBundle(installertools) {
- side = 'server'
- libraries()
- },
- extractBundle(installertools) {
- side = 'server'
- jar '{MINECRAFT_JAR}', '{MC_UNPACKED}'
- cache '{MC_UNPACKED}', '{MC_UNPACKED_SHA}'
- },
- step(binarypatcher) {
- side = 'server'
- args = [
- '--clean', '{MC_UNPACKED}',
- '--output', '{PATCHED}',
- '--apply', '{BINPATCH}',
- '--data', '--unpatched',
- '--store'
- ]
- cache '{PATCHED}', '{PATCHED_SHA}'
- },
- step(binarypatcher) {
- side = 'client'
- args = [
- '--clean', '{MINECRAFT_JAR}',
- '--output', '{PATCHED}',
- '--apply', '{BINPATCH}',
- '--data', '--unpatched',
- '--store',
- '--marker', '.forge_patched_minecraft'
- ]
- cache '{PATCHED}', '{PATCHED_SHA}'
- }
- ]
- }
-
- launcherJson {
- // These are flags to preserve glitchy old behavior to make diffing easier, removing when migrating to production is recommended
- sortLibraries = false // Don't sort, makes things non-deterministic, but easier to diff old versions
- duplicateLibraries = true // Our 'bootstrap' layer go added twice
- librariesLast = false // Makes libraries be added before args
-
- id = launcherId
- inheritsFrom = minecraftVersion
- mainClass = 'net.minecraftforge.bootstrap.ForgeBootstrap'
- gameArgs = [ '--launchTarget', 'forge_client' ]
- jvmArgs = [ '-Djava.net.preferIPv6Addresses=system', '-XX:+UseCompactObjectHeaders' ]
- }
-}
-
-final mdkGradleWrapper = tasks.register('mdkGradleWrapper', Wrapper) {
- gradleVersion = '9.5.0'
- scriptFile = layout.buildDirectory.dir("wrapper/" + gradleVersion + "/gradlew")
- jarFile = layout.buildDirectory.dir("wrapper/" + gradleVersion + "/gradle/wrapper/gradle-wrapper.jar")
-}
-
-final mdkZip = tasks.register('mdkZip', Zip) {
- dependsOn mdkGradleWrapper
-
- archiveBaseName = project.name
- archiveClassifier = 'mdk'
- archiveVersion = project.version
- destinationDirectory = file('build/libs')
- from(EXTRA_TXTS)
-
- from mdkGradleWrapper.map(Wrapper.&getScriptFile)
- from mdkGradleWrapper.map(Wrapper.&getBatchScript)
- into('gradle/wrapper/') {
- from mdkGradleWrapper.map(Wrapper.&getJarFile)
- from mdkGradleWrapper.map(Wrapper.&getPropertiesFile)
- }
- from(rootProject.file('mdk/')){
- rootProject.file('mdk/gitignore.txt').eachLine {
- if (!it.trim().isEmpty() && !it.trim().startsWith('#'))
- exclude it
- }
- filter(ReplaceTokens, tokens: [
- FORGE_VERSION: forgeVersion,
- FORGE_GROUP: project.group,
- FORGE_NAME: project.name,
- MC_VERSION: minecraftVersion,
- FORGE_SPEC_VERSION: gitversion.info.tag.split("\\.")[0],
- MC_NEXT_VERSION: minecraftNextVersion,
- EVENTBUS_VERSION: libs.versions.eventbus.get()
- ])
- rename 'gitignore\\.txt', '.gitignore'
- rename 'gitattributes\\.txt', '.gitattributes'
- }
- from(rootProject.file('src/test/java/com/example/examplemod/')) {
- into('src/main/java/com/example/examplemod/')
- }
- from(rootProject.file('src/test/generated/mdk_datagen/')) {
- into('src/main/resources/')
- exclude '**/.cache/'
- }
-}
-
-/*
-tasks.named('javadoc', Javadoc) {
- description = 'Generates the combined javadocs for the FML projects and the main Forge project'
- var includedProjects = [ ':fmlcore', ':fmlloader', ':javafmllanguage', ':mclanguage', ':forge-transformers' ]
- source includedProjects.collect { project(it).sourceSets.main.allJava }
- classpath = classpath + files(includedProjects.collect { project(it).sourceSets.main.compileClasspath })
-
- var docsDir = rootProject.file('src/docs/')
- inputs.dir(docsDir)
- .withPropertyName('docs resources directory')
- .withPathSensitivity(PathSensitivity.RELATIVE)
- .optional()
-
- failOnError = false
-
- // Exclude the Minecraft classes if not enabled
- if (!project.hasProperty('generateAllDocumentation')) {
- exclude 'net/minecraft/**'
- exclude 'com/mojang/**'
- }
- exclude 'mcp/**'
-
- options {
- stylesheetFile = new File(docsDir, 'stylesheet.css')
-
- tags = [
- 'apiNote:a:API Note:',
- 'implSpec:a:Implementation Requirements:',
- 'implNote:a:Implementation Note:'
- ]
-
- groups = [
- 'Forge Mod Loader': [
- 'net.minecraftforge.fml.common.asm*',
- 'net.minecraftforge.fml.loading*',
- 'net.minecraftforge.fml.server*'
- ],
- 'FML Core': [
- 'net.minecraftforge.fml',
- 'net.minecraftforge.fml.config*',
- 'net.minecraftforge.fml.event*',
- 'net.minecraftforge.fml.util*'
- ],
- 'FML Common': [
- 'net.minecraftforge.fml.core',
- 'net.minecraftforge.fml.event.config',
- 'net.minecraftforge.fml.event.lifecycle'
- ],
- 'FML Java/MC Language Providers': [
- 'net.minecraftforge.fml.common',
- 'net.minecraftforge.fml.javafmlmod',
- 'net.minecraftforge.fml.mclanguageprovider'
- ],
- 'Minecraft Forge API': [
- 'net.minecraftforge*'
- ]
- ]
-
- author = false
- noSince = true
- noHelp = true
-
- 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}
"
- }
-
- doLast {
- project.copy {
- from docsDir
- exclude '/stylesheet.css'
- into destinationDir
- }
- }
-}
-*/
-
-publishing {
repositories {
- maven gradleutils.publishingForgeMaven
+ mavenLocal()
}
+}
- 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
- }
+if (System.env.TEAMCITY_VERSION) {
+ //Only setup the CI environment if and only if the environment variables are set.
+ tasks.named('configureTeamCity').configure {
+ doLast {
+ println "##teamcity[buildNumber '${project(':forge').version}']"
+ println "##teamcity[setParameter name='env.PUBLISHED_JAVA_ARTIFACT_VERSION' value='${project(':forge').version}']"
}
}
}
-
-
-/*
-// 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
- 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) }
- }
- }
-}
-*/
-// endregion
-// We dont have any unit tests, so disable this error
-tasks.withType(AbstractTestTask).configureEach {
- failOnNoDiscoveredTests = false
-}
-// This shouldn't be needed according to the Gradle devs, as we never run these commands together.
-// But in another case of Gradle being gradle, here we are
-[ '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 gradlew dependencyUpdates --no-parallel
-//noinspection UnnecessaryQualifiedReference
-tasks.named('dependencyUpdates', com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask) {
- resolutionStrategy {
- mcpBase.dependencies.get().forEach {dep -> force(dep) } // Force all vanilla dependencies to their correct versions
- force(earlyDisplayLibs.slf4j.jdk14) // Force slf4j implementation, its tied to the api from the manifest
- }
-}
\ No newline at end of file
diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore
new file mode 100644
index 0000000000..2979d33310
--- /dev/null
+++ b/buildSrc/.gitignore
@@ -0,0 +1,3 @@
+/.gradle/
+/build/
+/out/
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 0000000000..c3e2c4e2b5
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,14 @@
+repositories {
+ maven { url = 'https://maven.minecraftforge.net/' }
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.ow2.asm:asm:9.9.1'
+ implementation 'org.ow2.asm:asm-tree:9.9.1'
+ implementation 'net.minecraftforge:srgutils:0.6.2'
+ implementation 'net.minecraftforge:JarJarMetadata:0.3.27'
+ implementation 'commons-io:commons-io:2.13.0'
+ implementation 'com.google.code.gson:gson:2.10.1'
+ implementation 'org.eclipse.jgit:org.eclipse.jgit:6.7.0.202309050840-r'
+}
diff --git a/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BundleList.groovy b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BundleList.groovy
new file mode 100644
index 0000000000..ad9bed5f55
--- /dev/null
+++ b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BundleList.groovy
@@ -0,0 +1,67 @@
+package net.minecraftforge.forge.tasks
+
+import org.gradle.api.tasks.*
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.bundling.AbstractArchiveTask
+
+import java.util.zip.ZipFile
+
+abstract class BundleList extends DefaultTask {
+ @InputFiles abstract ConfigurableFileCollection getConfig()
+ @InputFile abstract RegularFileProperty getServerBundle()
+ @OutputFile abstract RegularFileProperty getOutput()
+
+ BundleList() {
+ config.setFrom(project.configurations.installer)
+ output.convention(project.layout.buildDirectory.file("$name/output.list"))
+ configure {
+ dependsOn(project.tasks.universalJar)
+ inputs.file(project.tasks.universalJar.archiveFile)
+ dependsOn(project.tasks.applyServerBinPatches)
+ inputs.file(project.tasks.applyServerBinPatches.output)
+ }
+ }
+
+ @TaskAction
+ void run() {
+ def entries = [:] as TreeMap
+ def resolved = project.configurations.installer.resolvedConfiguration.resolvedArtifacts
+ for (def dep : resolved) {
+ def info = Util.getMavenInfoFromDep(dep)
+ //println("$dep.file.sha1\t$info.name\t$info.path")
+ entries.put("$info.art.group:$info.art.name", "$dep.file.sha256\t$info.name\t$info.path")
+ }
+
+ var packed = (AbstractArchiveTask) project.tasks.universalJar
+ var info = Util.getMavenInfoFromTask(packed)
+ def file = packed.archiveFile.get().asFile
+ entries.put("$info.art.group:$info.art.name:$info.art.classifier", "$file.sha256\t$info.name\t$info.path")
+
+ var classifier = 'server'
+ var genned = project.tasks.applyServerBinPatches
+ info = Util.getMavenInfoFromTask(genned, classifier)
+ file = genned.output.get().asFile
+ entries.put("$info.art.group:$info.art.name:$info.art.classifier", "$file.sha256\t$info.name\t$info.path")
+
+ try (def zip = new ZipFile(serverBundle.get().asFile)) {
+ def entry = zip.getEntry('META-INF/libraries.list')
+ def data = zip.getInputStream(entry).text.split('\n')
+ for (def line : data) {
+ def (sha, artifact, path) = line.split('\t')
+ def (group, name, other) = artifact.split(':', 3)
+ //println("Group: $group Name: $name")
+ def key = "$group:$name"
+ if (other.indexOf(':') != -1){
+ key += ':' + other.split(':', 2)[1]
+ //println("\tKey: $key")
+ }
+ if (!entries.containsKey(key))
+ entries.put(key, line)
+ }
+ }
+
+ output.get().asFile.text = entries.values().join('\n')
+ }
+}
diff --git a/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodeFinder.groovy b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodeFinder.groovy
new file mode 100644
index 0000000000..8f8271f490
--- /dev/null
+++ b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodeFinder.groovy
@@ -0,0 +1,52 @@
+package net.minecraftforge.forge.tasks
+
+import groovy.json.JsonBuilder
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.TaskAction
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.FieldNode
+import org.objectweb.asm.tree.MethodNode
+
+@CompileStatic
+abstract class BytecodeFinder extends DefaultTask {
+ @InputFile abstract RegularFileProperty getJar()
+ // It should be fine to mark the output as internal as we want to control when we run it anyways.
+ // This also shuts Gradle 8 up about implicit task dependencies.
+ @Internal abstract RegularFileProperty getOutput()
+
+ BytecodeFinder() {
+ output.convention(project.layout.buildDirectory.dir(name).map { it.file("output.json") })
+ }
+
+ @TaskAction
+ protected void exec() {
+ Util.init()
+
+ var outputFile = output.get().asFile
+ if (outputFile.exists())
+ outputFile.delete()
+
+ pre()
+
+ Util.processClassNodes(jar.get().asFile, this.&process)
+
+ post()
+ outputFile.text = new JsonBuilder(getData()).toPrettyString()
+ }
+
+
+ protected process(ClassNode node) {
+ if (node.fields !== null) node.fields.each { process(node, it) }
+ if (node.methods !== null) node.methods.each { process(node, it) }
+ }
+
+ protected pre() {}
+ protected process(ClassNode parent, FieldNode node) {}
+ protected process(ClassNode parent, MethodNode node) {}
+ protected post() {}
+ protected abstract Object getData()
+}
diff --git a/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodePredicateFinder.groovy b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodePredicateFinder.groovy
new file mode 100644
index 0000000000..b0efa482cc
--- /dev/null
+++ b/buildSrc/src/main/groovy/net/minecraftforge/forge/tasks/BytecodePredicateFinder.groovy
@@ -0,0 +1,48 @@
+package net.minecraftforge.forge.tasks
+
+import groovy.transform.CompileStatic
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Internal
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.MethodNode
+
+@CompileStatic
+abstract class BytecodePredicateFinder extends BytecodeFinder {
+
+ @Internal
+ abstract Property> getPredicate()
+
+ private final Map> matches = new TreeMap<>(Comparator.naturalOrder())
+
+ @Override
+ protected process(ClassNode parent, MethodNode node) {
+ for (final current : node.instructions) {
+ if (predicate.get().call(parent, node, current)) {
+ var methods = matches.compute(parent.name, { k, v -> v ?: new ArrayList<>() })
+
+ // only add non-synthetic methods
+ if ((node.access & Opcodes.ACC_SYNTHETIC) == 0) {
+ methods.add(node.name + node.desc)
+ }
+
+ return
+ }
+ }
+ }
+
+ @Internal
+ @Override
+ protected Object getData() {
+ var array = new ArrayList