diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3fb3fd7e7f..30fa5f916e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -10,4 +10,4 @@ assignees: '' - + diff --git a/.github/ISSUE_TEMPLATE/issue_report.md b/.github/ISSUE_TEMPLATE/issue_report.md index 9095acc8f3..6972478776 100644 --- a/.github/ISSUE_TEMPLATE/issue_report.md +++ b/.github/ISSUE_TEMPLATE/issue_report.md @@ -11,6 +11,7 @@ assignees: '' + **Minecraft Version:** {Minecraft version} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5fdf3fe6d6..ea7d5307b8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,7 +2,7 @@ name: Publish on: push: - branches: [ '1.21.11' ] + branches: [ '26.2' ] permissions: contents: read diff --git a/.github/workflows/pull_request_review.yml b/.github/workflows/pull_request_review.yml index 7f44cbdb09..0bb812509c 100644 --- a/.github/workflows/pull_request_review.yml +++ b/.github/workflows/pull_request_review.yml @@ -7,7 +7,7 @@ jobs: name: Upload payload runs-on: ubuntu-latest steps: - - uses: actions/upload-artifact@v3 # Payload artifact is consumed in Actionable + - uses: actions/upload-artifact@v4 # Payload artifact is consumed in Actionable with: name: payload path: ${{ github.event_path }} \ No newline at end of file diff --git a/.github/workflows/pull_request_review_comment.yml b/.github/workflows/pull_request_review_comment.yml index 2c3e5bc54b..74233a353d 100644 --- a/.github/workflows/pull_request_review_comment.yml +++ b/.github/workflows/pull_request_review_comment.yml @@ -7,7 +7,7 @@ jobs: name: Upload payload runs-on: ubuntu-latest steps: - - uses: actions/upload-artifact@v3 # Payload artifact is consumed in Actionable + - uses: actions/upload-artifact@v4 # Payload artifact is consumed in Actionable with: name: payload path: ${{ github.event_path }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4ae87a4951..c134175e62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +#forgedev dev if the folder exists in here +forgedev + #eclipse **/bin **/.settings @@ -22,10 +25,12 @@ /*/build /*/.gradle +# Minecraft +/run +/*.launch + # Projects repo, either ignore it, or ignore patches. -/projects/mcp/ -/projects/clean/ -/projects/forge/ +src/minecraft #occupational hazards /projects/**/build/ @@ -33,6 +38,7 @@ /projects/**/run/ /projects/**/*.launch /repo/ +/rejects-*/ src/*/generated/**/.cache/ # Generated by gradle every import @@ -46,3 +52,9 @@ src/*/generated/**/.cache/ /*/.gitignore /*/.factorypath /*/.apt_generated/ +/fmlcore/logs/ +/lib/ +/_actual/ +/runs/ +/forge.ipr +/forge.iws diff --git a/CREDITS.txt b/CREDITS.txt deleted file mode 100644 index 6ec8f004bd..0000000000 --- a/CREDITS.txt +++ /dev/null @@ -1,65 +0,0 @@ -Minecraft Forge: Credits/Thank You - -Forge is a set of tools and modifications to the Minecraft base game code to assist -mod developers in creating new and exciting content. It has been in development for -several years now, but I would like to take this time thank a few people who have -helped it along its way. - -First, the people who originally created the Forge projects way back in Minecraft -alpha. Eloraam of RedPower, and SpaceToad of Buildcraft, without their acceptiance -of me taking over the project, who knows what Minecraft modding would be today. - -Secondly, someone who has worked with me, and developed some of the core features -that allow modding to be as functional, and as simple as it is, cpw. For developing -FML, which stabilized the client and server modding ecosystem. As well as the base -loading system that allows us to modify Minecraft's code as elegently as possible. - -Mezz, who has stepped up as the issue and pull request manager. Helping to keep me -sane as well as guiding the community into creating better additions to Forge. - -Searge, Bspks, Fesh0r, ProfMobious, and all the rest over on the MCP team {of which -I am a part}. For creating some of the core tools needed to make Minecraft modding -both possible, and as stable as can be. - On that note, here is some specific information of the MCP data we use: - * Minecraft Coder Pack (MCP) * - Forge Mod Loader and Minecraft Forge have permission to distribute and automatically - download components of MCP and distribute MCP data files. This permission is not - transitive and others wishing to redistribute the Minecraft Forge source independently - should seek permission of MCP or remove the MCP data files and request their users - to download MCP separately. - -And lastly, the countless community members who have spent time submitting bug reports, -pull requests, and just helping out the community in general. Thank you. - ---LexManos - -========================================================================= - -This is Forge Mod Loader. - -You can find the source code at all times at https://github.com/MinecraftForge/MinecraftForge/tree/1.12.x/src/main/java/net/minecraftforge/fml - -This minecraft mod is a clean open source implementation of a mod loader for minecraft servers -and minecraft clients. - -The code is authored by cpw. - -It began by partially implementing an API defined by the client side ModLoader, authored by Risugami. -https://www.minecraftforum.net/topic/75440- -This support has been dropped as of Minecraft release 1.7, as Risugami no longer maintains ModLoader. - -It also contains suggestions and hints and generous helpings of code from LexManos, author of MinecraftForge. -https://minecraftforge.net/ - -Additionally, it contains an implementation of topological sort based on that -published at http://keithschwarz.com/interesting/code/?dir=topological-sort - -It also contains code from the Maven project for performing versioned dependency -resolution. http://maven.apache.org/ - -It also contains a partial repackaging of the javaxdelta library from http://sourceforge.net/projects/javaxdelta/ -with credit to it's authors. - -Forge Mod Loader downloads components from the Minecraft Coder Pack -(http://mcp.ocean-labs.de/index.php/Main_Page) with kind permission from the MCP team. - diff --git a/LICENSE.txt b/LICENSE.txt index 249debe26b..51c22dd7db 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: http://minecraftforge.net/ +Homepage: https://minecraftforge.net/ https://github.com/MinecraftForge/MinecraftForge diff --git a/build.gradle b/build.gradle index a49df84377..76f7de0ad6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,54 +1,795 @@ -import net.minecraftforge.forge.tasks.* -import net.minecraftforge.gradleutils.PomUtils +import org.apache.tools.ant.filters.ReplaceTokens plugins { - 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 'java-library' + id 'idea' id 'eclipse' - id 'de.undercouch.download' version '5.4.0' - id 'net.minecraftforge.gradle.patcher' version '[6.0.46,6.2)' apply false - id 'net.minecraftforge.gradle.mcp' version '[6.0.46,6.2)' apply false - id 'net.minecraftforge.gradlejarsigner' version '1.0.4' - id 'org.barfuin.gradle.taskinfo' version '2.1.0' + 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' } -Util.init() //Init all our extension methods! +gradleutils.displayName = 'Forge' +group = 'net.minecraftforge' +description = 'Modifications to Minecraft to enable mod developers.' -ext { - VERSION = gitversion.getMCTagOffsetBranch(MC_VERSION) - FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1) +// 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) + } } -changelog { - from '47.999' +/* 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 ':forge:extractMapped' - if (findProject(':clean')) - dependsOn ':clean:extractMapped' + dependsOn forgedev.patches.apply } -tasks.register('doChecks') { - dependsOn ':forge:checkJarCompatibility' - dependsOn ':forge:publish' -} - -project(':mcp') { - apply plugin: 'net.minecraftforge.gradle.mcp' - mcp { - config MC_VERSION + '-' + MCP_VERSION - pipeline = 'joined' +sourceSets { + named('main') { + resources.srcDir 'src/main/generated' + } + named('test') { + resources.srcDir 'src/test/generated' } } -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}']" +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') } } } + +changelog { + from changelogBase + publishAll = false +} + +// 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) + } +} + +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 +} + +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' + } + } + } + + 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 = "