mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
211d3aa692 | ||
|
|
88bb2217e5 | ||
|
|
278bdfc132 | ||
|
|
66d4d888eb | ||
|
|
ee1e695124 | ||
|
|
6435274d1e | ||
|
|
6c3729d6e9 | ||
|
|
6a702686db | ||
|
|
d3476f3f80 | ||
|
|
6665cdcf4e | ||
|
|
d9665f6447 | ||
|
|
ec73fd5240 | ||
|
|
3bbdbacb81 | ||
|
|
478d8b3f18 | ||
|
|
03f928a3de | ||
|
|
4834f16aef | ||
|
|
7846d25606 | ||
|
|
77cb0c5c4e | ||
|
|
5e421e8b8b | ||
|
|
5f37e8af53 | ||
|
|
5ab792f1d7 | ||
|
|
38ebbf189c | ||
|
|
f247eebd55 | ||
|
|
555989cf10 | ||
|
|
49fe93b1b5 | ||
|
|
48167e93b4 | ||
|
|
2bd132a6f8 | ||
|
|
b8168a12df | ||
|
|
df271e0265 | ||
|
|
d7687a72d5 |
No files matched your search
@@ -2,7 +2,7 @@ name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '26.1' ]
|
||||
branches: [ '26.1.2' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
+13
-3
@@ -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/
|
||||
@@ -47,3 +52,8 @@ src/*/generated/**/.cache/
|
||||
/*/.factorypath
|
||||
/*/.apt_generated/
|
||||
/fmlcore/logs/
|
||||
/lib/
|
||||
/_actual/
|
||||
/runs/
|
||||
/forge.ipr
|
||||
/forge.iws
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
|
||||
+776
-37
@@ -1,57 +1,796 @@
|
||||
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.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'
|
||||
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'
|
||||
}
|
||||
repositories {
|
||||
mavenLocal()
|
||||
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:<em>API Note:</em>',
|
||||
'implSpec:a:<em>Implementation Requirements:</em>',
|
||||
'implNote:a:<em>Implementation Note:</em>'
|
||||
]
|
||||
|
||||
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 = "<div style=\"margin-top: 9px;padding: 5px 6px;\"><strong>${forgeVersion} for Minecraft ${minecraftVersion}</strong></div>"
|
||||
}
|
||||
|
||||
doLast {
|
||||
project.copy {
|
||||
from docsDir
|
||||
exclude '/stylesheet.css'
|
||||
into destinationDir
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
/.gradle/
|
||||
/build/
|
||||
/out/
|
||||
@@ -1,14 +0,0 @@
|
||||
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'
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
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')
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
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()
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
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<Closure<Boolean>> getPredicate()
|
||||
|
||||
private final Map<String, List<String>> 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<Object>()
|
||||
matches.forEach { c, m ->
|
||||
{
|
||||
array.add(
|
||||
'class': c,
|
||||
'methods': m
|
||||
)
|
||||
}
|
||||
}
|
||||
return array ?: { throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.') }()
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks;
|
||||
|
||||
import groovy.transform.CompileDynamic;
|
||||
import groovy.transform.CompileStatic;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Eclipse config files are literally just java properties, with the header cleaned up.
|
||||
* https://github.com/eclipse/buildship/blob/5b2c7fca7fa86cd74d71b3c099c7b1559eba038e/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/PreferenceStore.java#L238
|
||||
*
|
||||
* This does the same thing, as well as sorting alphabetically.
|
||||
* It also ignores all comments. We can add them latter if someone cares.
|
||||
*/
|
||||
@CompileStatic
|
||||
public class CleanProperties extends Properties {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String LINE_SEP = System.getProperty("line.separator");
|
||||
private static final String UNIX_LINE_SEP = "\n";
|
||||
private static final Charset ENCODING = StandardCharsets.UTF_8;
|
||||
|
||||
public CleanProperties load(File input) throws IOException {
|
||||
if (input.exists()) {
|
||||
try (Reader is = new InputStreamReader(new FileInputStream(input), ENCODING)) {
|
||||
super.load(is);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void store(File out) throws IOException {
|
||||
if (!out.getParentFile().exists())
|
||||
out.getParentFile().mkdirs();
|
||||
|
||||
try (OutputStream os = new FileOutputStream(out)) {
|
||||
store(os, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Enumeration<Object> keys() {
|
||||
Set<Object> ret = new TreeSet<>();
|
||||
for (Enumeration<?> e = super.keys(); e.hasMoreElements();)
|
||||
ret.add(e.nextElement());
|
||||
return Collections.enumeration(ret);
|
||||
}
|
||||
|
||||
@CompileDynamic
|
||||
@Override
|
||||
public Set<Map.Entry<Object, Object>> entrySet() {
|
||||
Set<Map.Entry<Object, Object>> ret = new TreeSet<>((l, r) -> ((String)l.getKey()).compareTo((String)r.getKey()));
|
||||
ret.addAll(super.entrySet());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(OutputStream out, String comments) throws IOException {
|
||||
out.write(clean().getBytes(ENCODING));
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Writer out, String comments) throws IOException {
|
||||
out.write(clean());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private String clean() throws IOException {
|
||||
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
|
||||
try {
|
||||
super.store(tmp, null);
|
||||
} finally {
|
||||
tmp.close();
|
||||
}
|
||||
|
||||
String ret = tmp.toString(ENCODING).replace(LINE_SEP, UNIX_LINE_SEP);
|
||||
ret = ret.substring(ret.indexOf(UNIX_LINE_SEP) + 1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.stc.FirstParam
|
||||
|
||||
import java.util.function.BiConsumer
|
||||
|
||||
public class ClosureHelper {
|
||||
BiConsumer<String, Closure> callback
|
||||
|
||||
public ClosureHelper(Closure cl, BiConsumer<String, Closure> callback) {
|
||||
this.callback = callback
|
||||
apply(this, cl)
|
||||
}
|
||||
|
||||
|
||||
def methodMissing(String name, Object args) {
|
||||
if (!args.class.isArray()) return
|
||||
Object[] aargs = (Object[])args
|
||||
|
||||
if (aargs.length == 1 && aargs[0] instanceof Closure) {
|
||||
this.callback.accept(name, (Closure)aargs[0])
|
||||
} else {
|
||||
throw new IllegalArgumentException('Unknown method: "' + name + '" with arguments ' + args + ' for ' + this)
|
||||
}
|
||||
}
|
||||
|
||||
static <T> T apply(T obj, @DelegatesTo(value = FirstParam, strategy = Closure.DELEGATE_FIRST) Closure cl) {
|
||||
cl.delegate = obj
|
||||
cl.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
cl()
|
||||
return obj
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.OutputFiles
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
abstract class DownloadLibraries extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInput()
|
||||
@OutputDirectory abstract DirectoryProperty getOutput()
|
||||
@OutputFile abstract RegularFileProperty getLibrariesOutput()
|
||||
|
||||
DownloadLibraries() {
|
||||
output.convention(project.layout.buildDirectory.dir(name))
|
||||
librariesOutput.convention(project.layout.buildDirectory.dir(name).map(d -> d.file('libraries.txt')))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
def run() {
|
||||
Util.init()
|
||||
File outputDir = output.get().asFile
|
||||
var libraries = new ArrayList<String>()
|
||||
|
||||
def json = input.get().asFile.json().libraries.each { lib ->
|
||||
//TODO: Thread?
|
||||
def artifacts = [lib.downloads.artifact] + lib.downloads.get('classifiers', [:]).values()
|
||||
artifacts.each{ art ->
|
||||
def target = new File(outputDir, art.path)
|
||||
libraries.add(target.absolutePath)
|
||||
if (!target.exists() || art.sha1 != target.sha1()) {
|
||||
project.logger.lifecycle("Downloading ${art.url}")
|
||||
if (!target.parentFile.exists()) {
|
||||
target.parentFile.mkdirs()
|
||||
}
|
||||
new URL(art.url).withInputStream { i ->
|
||||
target.withOutputStream { it << i }
|
||||
}
|
||||
if (art.sha1 != target.sha1()) {
|
||||
throw new IllegalStateException("Failed to download ${art.url} to ${target.canonicalPath} SHA Mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Files.write(librariesOutput.get().asFile.toPath(), libraries)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
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.*
|
||||
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
@CompileStatic
|
||||
abstract class ExtractFile extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInput()
|
||||
@Input abstract Property<String> getTarget()
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
var zip = new ZipFile(input.get().asFile);
|
||||
var entry = zip.getEntry(target.get())
|
||||
if (entry == null)
|
||||
throw new IllegalStateException(input.get().asFile.absolutePath + " does not contain " + target.get())
|
||||
var stream = zip.getInputStream(entry)
|
||||
output.get().asFile.withOutputStream { out ->
|
||||
stream.transferTo(out)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
|
||||
import org.gradle.api.tasks.*
|
||||
import org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*
|
||||
|
||||
abstract class FieldCompareFinder extends BytecodeFinder {
|
||||
@Nested
|
||||
Map<String, Search> fields = [:] as HashMap
|
||||
@Internal
|
||||
Map<Search, String> fieldsReverse = [:] as HashMap
|
||||
@Internal
|
||||
Map<String, Set<ObjectTarget>> targets = [:] as TreeMap
|
||||
|
||||
@Override
|
||||
protected pre() {
|
||||
//fields.each{ k,v -> logger.lifecycle("Fields: " + k + ' ' + v) }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected process(ClassNode parent, MethodNode node) {
|
||||
AbstractInsnNode last = null
|
||||
def parentInstance = new ObjectTarget(owner: parent.name, name: '', desc: '')
|
||||
for (int x = 0; x < node.instructions.size(); x++) {
|
||||
def current = node.instructions.get(x)
|
||||
if (current.opcode === IF_ACMPEQ || current.opcode === IF_ACMPNE) {
|
||||
if (last !== null && (last.opcode === GETSTATIC || last.opcode === GETFIELD)) {
|
||||
def target = new Search(cls: last.owner, name: last.name)
|
||||
def wanted = fieldsReverse.get(target)
|
||||
def original = fields.get(wanted)
|
||||
def instance = new ObjectTarget(owner: parent.name, name: node.name, desc: node.desc)
|
||||
if (wanted !== null && (original.blacklist === null || (!original.blacklist.contains(instance) && !original.blacklist.contains(parentInstance)))) {
|
||||
targets.computeIfAbsent(wanted, { k -> new TreeSet() }).add(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
last = current
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
@Override
|
||||
protected Object getData() {
|
||||
def ret = [:] as HashMap
|
||||
targets.forEach{ k, v ->
|
||||
def e = fields.get(k)
|
||||
ret[k] = [
|
||||
cls: e.cls,
|
||||
name: e.name,
|
||||
replacement: e.replacement,
|
||||
targets: v
|
||||
]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(excludes = ['replacement', 'blacklist'])
|
||||
static class Search {
|
||||
@Input
|
||||
String cls
|
||||
|
||||
@Input
|
||||
String name
|
||||
|
||||
@Input
|
||||
String replacement
|
||||
|
||||
@Nested
|
||||
@Optional
|
||||
Set<ObjectTarget> blacklist
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
return cls + '.' + name
|
||||
}
|
||||
|
||||
def blacklist(String owner, String name, String desc) {
|
||||
if (blacklist === null)
|
||||
blacklist = new HashSet<>()
|
||||
blacklist.add(new ObjectTarget(owner: owner, name: name, desc: desc))
|
||||
}
|
||||
def blacklist(String owner) {
|
||||
blacklist(owner, '', '')
|
||||
}
|
||||
}
|
||||
|
||||
void fields(Closure cl) {
|
||||
new ClosureHelper(cl, {name, ccl ->
|
||||
def search = ClosureHelper.apply(new Search(), ccl)
|
||||
this.fields.put(name, search)
|
||||
this.fieldsReverse.put(search, name)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@CompileStatic
|
||||
@TupleConstructor
|
||||
final class InheritanceData implements Annotatable {
|
||||
String name
|
||||
int access
|
||||
String superName
|
||||
List<String> interfaces = []
|
||||
Map<String, Method> methods = [:]
|
||||
Map<String, Field> fields = [:]
|
||||
List<Annotation> annotations = []
|
||||
|
||||
@TupleConstructor
|
||||
static final class Method implements Annotatable {
|
||||
int access
|
||||
String override
|
||||
List<Annotation> annotations = []
|
||||
}
|
||||
|
||||
@TupleConstructor
|
||||
static final class Field implements Annotatable {
|
||||
int access
|
||||
String desc
|
||||
List<Annotation> annotations = []
|
||||
}
|
||||
|
||||
@TupleConstructor
|
||||
static final class Annotation {
|
||||
String desc
|
||||
}
|
||||
|
||||
private static final Gson GSON = new Gson()
|
||||
static Map<String, InheritanceData> parse(File file) {
|
||||
try (final reader = file.newReader()) {
|
||||
return GSON.fromJson(reader, new TypeToken<Map<String, InheritanceData>>() {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
interface Annotatable {
|
||||
List<InheritanceData.Annotation> getAnnotations()
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.provider.Property
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
abstract class InstallerJar extends Zip {
|
||||
@Input @Optional abstract Property<Boolean> getFat()
|
||||
@Input @Optional abstract Property<Boolean> getOffline()
|
||||
|
||||
InstallerJar() {
|
||||
archiveClassifier.set('installer')
|
||||
archiveExtension.set('jar') // Needs to be Zip task to not override Manifest, so set extension
|
||||
destinationDirectory.set(project.layout.buildDirectory.dir('libs'))
|
||||
fat.convention(false)
|
||||
offline.convention(false)
|
||||
|
||||
def installerJson = project.tasks.installerJson
|
||||
def launcherJson = project.tasks.launcherJson
|
||||
def downloadInstaller = project.tasks.downloadInstaller
|
||||
|
||||
dependsOn(installerJson, launcherJson, downloadInstaller, project.configurations.installer)
|
||||
from(installerJson, launcherJson)
|
||||
|
||||
from(project.rootProject.file('/src/main/resources/url.png'))
|
||||
project.afterEvaluate {
|
||||
from(project.zipTree(downloadInstaller.output)) {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
if (fat.get() || offline.get()) {
|
||||
def cfg = project.tasks.register(name + "Config", Configure)
|
||||
cfg.get().configure {
|
||||
parent = this
|
||||
dependsOn(project.tasks.installerJson, project.tasks.launcherJson)
|
||||
}
|
||||
dependsOn(cfg)
|
||||
} else {
|
||||
// Things we ALWAYS bundle, this just the server shim jar, because the installer spec only says to extract the file.
|
||||
// I should make it allow downloads but thats a spec break, and this is just a ~14KB jar
|
||||
[
|
||||
project.tasks.serverShimJar // Server bootstrap executable jar
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def path = Util.getMavenInfoFromTask(packed).path
|
||||
from(packed) {
|
||||
rename { "maven/$path" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class Configure extends DefaultTask {
|
||||
public Zip parent
|
||||
private int count = 0;
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def deps = [:] as java.util.TreeMap
|
||||
|
||||
// Gather all things that need downloading
|
||||
[
|
||||
project.tasks.installerJson,
|
||||
project.tasks.launcherJson
|
||||
].each { task ->
|
||||
def json = task.output.get().asFile.json
|
||||
json.libraries.each { lib ->
|
||||
if (lib.downloads?.artifact?.url !== null && !lib.downloads.artifact.url.isEmpty())
|
||||
deps.put(lib.name, lib.downloads.artifact)
|
||||
}
|
||||
}
|
||||
|
||||
// First find things we build in this project.
|
||||
[
|
||||
project.tasks.universalJar, // Forge runtime code
|
||||
project.tasks.serverShimJar // Shim jar for dedicated server
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def name = Util.getMavenInfoFromTask(packed).name
|
||||
def info = deps.remove(name)
|
||||
if (info !== null) {
|
||||
println("Adding: $packed.path $name")
|
||||
parent.from(packed) {
|
||||
rename { "maven/$info.path" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find any artifacts from the 'installer' config
|
||||
// This config specifies the runtime files we intend for the interaller to have.
|
||||
// And are typically what we would be developing and testing alongside Forge.
|
||||
// So we may have local modified versions
|
||||
def cfg = project.configurations.installer
|
||||
while (cfg != null) {
|
||||
//println('')
|
||||
def resolved = cfg.resolvedConfiguration.resolvedArtifacts
|
||||
int found = 0
|
||||
for (def dep : resolved) {
|
||||
def name = Util.getMavenInfoFromDep(dep).name
|
||||
def info = deps.remove(name)
|
||||
if (info == null) {
|
||||
//println("Skipping: $name")
|
||||
continue
|
||||
}
|
||||
//println("-$name")
|
||||
found++
|
||||
addFile(dep.file, info)
|
||||
}
|
||||
|
||||
if (deps.isEmpty()) {
|
||||
cfg = null
|
||||
continue
|
||||
}
|
||||
|
||||
// Prevent infinite loops if something fucky happens
|
||||
if (found == 0)
|
||||
throw new IllegalStateException("Failed to find any installer dependencies")
|
||||
|
||||
def seen = [] as Set
|
||||
cfg = project.configurations.detachedConfiguration()
|
||||
cfg.transitive = false
|
||||
for (def key : deps.keySet()) {
|
||||
def (group, artifact, other) = key.split(':', 3)
|
||||
// Only resolve unique group:artifact so we don't get version overrides
|
||||
if (seen.add(group + ':' + artifact)) {
|
||||
//println("+$key")
|
||||
cfg.dependencies.add(project.dependencies.create(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addFile(file, info) {
|
||||
boolean pack = parent.offline.get() || info.url.isEmpty()
|
||||
|
||||
// If it's a offline jar just always pack
|
||||
if (!pack) {
|
||||
try {
|
||||
var remote = new URL("${info.url}.sha1").getText('UTF-8')
|
||||
pack = info.sha1 != remote
|
||||
} catch (FileNotFoundException e) {
|
||||
pack = !info.url.startsWith('https://libraries.minecraft.net/')
|
||||
// Oh noes its not there!
|
||||
}
|
||||
}
|
||||
|
||||
if (pack) {
|
||||
println("Adding: $file.absolutePath")
|
||||
parent.from(file) {
|
||||
rename { "maven/$info.path" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
abstract class InstallerJson extends DefaultTask {
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||
@Input @Optional final Map<String, Object> libraries = new LinkedHashMap<>()
|
||||
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||
@InputFile abstract RegularFileProperty getIcon()
|
||||
@Input abstract Property<String> getLauncherJsonName()
|
||||
@Input abstract Property<String> getLogo()
|
||||
@Input abstract Property<String> getMirrors()
|
||||
@Input abstract Property<String> getWelcome()
|
||||
|
||||
InstallerJson() {
|
||||
launcherJsonName.convention('/version.json')
|
||||
logo.convention('/big_logo.png')
|
||||
mirrors.convention('https://files.minecraftforge.net/mirrors-2.0.json')
|
||||
welcome.convention("Welcome to the ${project.name.capitalize()} installer.")
|
||||
output.convention(project.layout.buildDirectory.file('libs/install_profile.json'))
|
||||
|
||||
project.afterEvaluate {
|
||||
[
|
||||
project.tasks.universalJar,
|
||||
project.tasks.serverShimJar
|
||||
].forEach { packed ->
|
||||
dependsOn(packed)
|
||||
input.from packed.archiveFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def libs = libraries
|
||||
[
|
||||
project.tasks.universalJar,
|
||||
project.tasks.serverShimJar
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
libs.put(info.name, [
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "https://maven.minecraftforge.net/$info.path",
|
||||
sha1: packed.archiveFile.get().asFile.sha1(),
|
||||
size: packed.archiveFile.get().asFile.length()
|
||||
]
|
||||
]
|
||||
])
|
||||
}
|
||||
json.libraries = libs.values().sort{a,b -> a.name.compareTo(b.name)}
|
||||
json.icon = "data:image/png;base64," + new String(Base64.getEncoder().encode(Files.readAllBytes(icon.get().asFile.toPath())))
|
||||
json.json = launcherJsonName.get()
|
||||
json.logo = logo.get()
|
||||
if (!mirrors.get().isEmpty())
|
||||
json.mirrorList = mirrors.get()
|
||||
json.welcome = welcome.get()
|
||||
|
||||
Files.writeString(output.get().getAsFile().toPath(), new JsonBuilder(json).toPrettyString())
|
||||
}
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.forge.tasks;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarIdentifier;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarMetadata;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedVersion;
|
||||
import net.minecraftforge.jarjar.metadata.Metadata;
|
||||
import net.minecraftforge.jarjar.metadata.MetadataIOHandler;
|
||||
import net.minecraftforge.jarjar.metadata.json.ArtifactVersionSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedJarIdentifierSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedJarMetadataSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedVersionSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.MetadataSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.VersionRangeSerializer;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||
import org.apache.maven.artifact.versioning.VersionRange;
|
||||
import org.codehaus.groovy.runtime.InvokerHelper;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.FileCollectionDependency;
|
||||
import org.gradle.api.artifacts.MinimalExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.ModuleDependency;
|
||||
import org.gradle.api.artifacts.ModuleIdentifier;
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier;
|
||||
import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.file.ProjectLayout;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
// TODO SUPER SUPER SUPER UGLY, CLEAN UP IN FORGEDEV 7
|
||||
@Deprecated(forRemoval = true) // Will be moved to JarJar plugin in ForgeDev 7
|
||||
public abstract class JarJarMetadataOptions extends DefaultTask {
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.registerTypeAdapter(VersionRange.class, new VersionRangeSerializer())
|
||||
.registerTypeAdapter(ArtifactVersion.class, new ArtifactVersionSerializer())
|
||||
.registerTypeAdapter(DefaultArtifactVersion.class, new ArtifactVersionSerializer())
|
||||
.registerTypeAdapter(ContainedJarIdentifier.class, new ContainedJarIdentifierSerializer())
|
||||
.registerTypeAdapter(ContainedJarMetadata.class, new ContainedJarMetadataSerializer())
|
||||
.registerTypeAdapter(ContainedVersion.class, new ContainedVersionSerializer())
|
||||
.registerTypeAdapter(Metadata.class, new MetadataSerializer())
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
protected abstract @Input SetProperty<ResolvedDependencyInfoImpl> getResolvedDependencies();
|
||||
|
||||
protected abstract @OutputFile RegularFileProperty getMetadataFile();
|
||||
|
||||
protected abstract @Inject ProjectLayout getLayout();
|
||||
|
||||
// NOTE: I'm not adding a non-provider version. please just use the version catalog entries for now.
|
||||
public void add(Provider<MinimalExternalModuleDependency> dependency, Action<? super ResolvedDependencyInfo> action) {
|
||||
this.getResolvedDependencies().add(dependency.map(d -> {
|
||||
var ret = ResolvedDependencyInfoImpl.from(this.getProject().getConfigurations(), d);
|
||||
action.execute(ret);
|
||||
return ret;
|
||||
}));
|
||||
}
|
||||
|
||||
@Inject
|
||||
public JarJarMetadataOptions() {
|
||||
this.getMetadataFile().convention(this.getLayout().getBuildDirectory().file(this.getName() + "/options.json"));
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
record ForgeLocaterOptions(String resource, String layer, String id, List<ContainedJarMetadata> deps, ContainedJarMetadata meta, boolean nested) { }
|
||||
|
||||
var resolved = this.getResolvedDependencies().get();
|
||||
var jars = new ArrayList<ForgeLocaterOptions>(resolved.size());
|
||||
for (var dependency : resolved) {
|
||||
var deps = new ArrayList<ContainedJarMetadata>();
|
||||
try (var zip = new ZipFile(dependency.artifact)) {
|
||||
var entry = zip.getEntry("META-INF/jarjar/metadata.json");
|
||||
if (entry != null) {
|
||||
try (var stream = zip.getInputStream(entry)) {
|
||||
var meta = MetadataIOHandler.fromStream(stream).orElse(null);
|
||||
if (meta == null)
|
||||
throw new IllegalStateException("Corrupt metadata.json in " + dependency.artifact.getAbsolutePath());
|
||||
for (var dep : meta.jars())
|
||||
deps.add(new ContainedJarMetadata(dep.identifier(), dep.version(), "", dep.isObfuscated()));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
jars.add(new ForgeLocaterOptions(
|
||||
dependency.resource,
|
||||
dependency.layer,
|
||||
dependency.identifier,
|
||||
deps,
|
||||
new ContainedJarMetadata(
|
||||
new ContainedJarIdentifier(validateGroup(dependency), dependency.module.getName()),
|
||||
new ContainedVersion(null, parseVersion(dependency)),
|
||||
Objects.requireNonNull(dependency.path, "Dependency path is unspecified: " + dependency.asString),
|
||||
false
|
||||
),
|
||||
dependency.nested
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
record Meta(List<ForgeLocaterOptions> options){}
|
||||
|
||||
Files.writeString(
|
||||
this.getMetadataFile().getAsFile().get().toPath(),
|
||||
GSON.toJson(new Meta(jars), Meta.class)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String validateGroup(ResolvedDependencyInfoImpl dependency) {
|
||||
try {
|
||||
return Objects.requireNonNull(dependency.module.getGroup());
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Module dependency has no group: " + dependency.asString, e);
|
||||
}
|
||||
}
|
||||
|
||||
private ArtifactVersion parseVersion(ResolvedDependencyInfoImpl resolved) {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec(Objects.requireNonNull(resolved.version)).getRecommendedVersion();
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version is invalid for: " + resolved.asString, e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Version is unspecified for: " + resolved.asString, e);
|
||||
}
|
||||
}
|
||||
|
||||
private VersionRange parseVersionRange(ResolvedDependencyInfoImpl dependency) {
|
||||
if (dependency.hasManuallySpecifiedRange) {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec(dependency.versionRange);
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version is invalid for: " + dependency.asString, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec("[%s,)".formatted(Objects.requireNonNull(dependency.versionRange)));
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version range is invalid for: " + dependency.asString, e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Version is unspecified for: " + dependency.asString, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResolvedDependencyInfo {
|
||||
void containedJarMetadata(Action<? super ContainedJarMetadataInfo> action);
|
||||
|
||||
void setResource(String resource);
|
||||
|
||||
void setLayer(String layer);
|
||||
|
||||
void setId(String identifier);
|
||||
|
||||
void setNested(boolean nested);
|
||||
|
||||
interface ContainedJarMetadataInfo {
|
||||
void setGroup(String group);
|
||||
|
||||
void setName(String name);
|
||||
|
||||
void setPath(String version);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ResolvedDependencyInfoImpl implements ResolvedDependencyInfo, ResolvedDependencyInfo.ContainedJarMetadataInfo, Serializable {
|
||||
private static final @Serial long serialVersionUID = -7577318115877822993L;
|
||||
|
||||
final MinimalModuleVersionIdentifier module;
|
||||
final String version;
|
||||
String versionRange;
|
||||
boolean hasManuallySpecifiedRange;
|
||||
boolean nested;
|
||||
final File artifact;
|
||||
String path;
|
||||
String resource;
|
||||
String layer;
|
||||
String identifier;
|
||||
final String asString;
|
||||
|
||||
public ResolvedDependencyInfoImpl(MinimalModuleVersionIdentifier module, String version, File artifact, String asString) {
|
||||
this.module = module;
|
||||
this.version = version;
|
||||
this.artifact = artifact;
|
||||
this.asString = asString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containedJarMetadata(Action<? super ContainedJarMetadataInfo> action) {
|
||||
action.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(String group) {
|
||||
this.module.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.module.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayer(String layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNested(boolean nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
static Set<File> getFiles(Set<ResolvedDependencyInfoImpl> resolvedDependencies) {
|
||||
var ret = new HashSet<File>(resolvedDependencies.size());
|
||||
for (var dependency : resolvedDependencies) {
|
||||
ret.add(dependency.artifact);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ResolvedDependencyInfoImpl from(ConfigurationContainer configurations, Dependency dependency) {
|
||||
var group = dependency.getGroup();
|
||||
var name = dependency.getName();
|
||||
var version = dependency.getVersion();
|
||||
|
||||
if (dependency instanceof FileCollectionDependency filesDependency) {
|
||||
File artifact;
|
||||
try {
|
||||
artifact = filesDependency.getFiles().getSingleFile();
|
||||
} catch (IllegalStateException e) {
|
||||
// TODO fileCollectionDependencyIsNotSingleFile
|
||||
throw e;
|
||||
}
|
||||
|
||||
return new ResolvedDependencyInfoImpl(
|
||||
new MinimalModuleVersionIdentifier(group, name, version),
|
||||
version,
|
||||
artifact,
|
||||
filesDependency.toString()
|
||||
);
|
||||
} else if (dependency instanceof ModuleDependency moduleDependency) {
|
||||
moduleDependency = moduleDependency.copy();
|
||||
if (moduleDependency instanceof ExternalModuleDependency externalModuleDependency) {
|
||||
externalModuleDependency.version(v -> v.strictly(version.toString()));
|
||||
}
|
||||
|
||||
var detachedConfiguration = configurations.detachedConfiguration(moduleDependency);
|
||||
detachedConfiguration.setTransitive(false);
|
||||
|
||||
ResolvedDependencyInfoImpl ret = null;
|
||||
for (var artifact : detachedConfiguration.getResolvedConfiguration().getFirstLevelModuleDependencies().iterator().next().getModuleArtifacts()) {
|
||||
var fileName = getFileName(artifact);
|
||||
if (!fileName.endsWith(".jar"))
|
||||
continue;
|
||||
|
||||
if (ret != null)
|
||||
throw new IllegalArgumentException("Module dependency has too many Jar artifacts: " + moduleDependency);
|
||||
|
||||
ret = new ResolvedDependencyInfoImpl(
|
||||
new MinimalModuleVersionIdentifier(group, name, artifact.getModuleVersion().getId().getVersion()),
|
||||
version,
|
||||
artifact.getFile(),
|
||||
moduleDependency.toString()
|
||||
);
|
||||
}
|
||||
if (ret == null)
|
||||
throw new IllegalArgumentException("Module dependency has no Jar artifacts: " + moduleDependency);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported dependency type: " + dependency.getClass().getName() + " -- " + dependency);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFileName(ResolvedArtifact artifact) {
|
||||
try {
|
||||
return InvokerHelper.getProperty(artifact.getId(), "fileName").toString();
|
||||
} catch (Throwable e) {
|
||||
// NOTE: Why not just use this to begin with?
|
||||
// ComponentArtifactIdentifier can have a getFileName() method, which doesn't necessarily resolve the file itself.
|
||||
// This allows us to get the name of the file to be used without asking Gradle to download the file.
|
||||
// So, if a file is not a JAR file, we can check the name without actually downloading it.
|
||||
return artifact.getFile().getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
var that = (ResolvedDependencyInfoImpl) obj;
|
||||
return Objects.equals(this.module, that.module) &&
|
||||
Objects.equals(this.version, that.version) &&
|
||||
Objects.equals(this.versionRange, that.versionRange) &&
|
||||
Objects.equals(this.artifact, that.artifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(module, version, versionRange, artifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResolvedDependencyInfo[" +
|
||||
"module=" + module + ", " +
|
||||
"fixedVersion=" + version + ", " +
|
||||
"versionRange=" + versionRange + ", " +
|
||||
"artifact=" + artifact + ']';
|
||||
}
|
||||
|
||||
static final class MinimalModuleVersionIdentifier implements ModuleIdentifier, ModuleVersionIdentifier {
|
||||
private static final @Serial long serialVersionUID = -955346236759069739L;
|
||||
|
||||
private String group;
|
||||
private String name;
|
||||
private final String version;
|
||||
|
||||
@Inject
|
||||
public MinimalModuleVersionIdentifier(String group, String name, String version) {
|
||||
this.group = group;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleIdentifier getModule() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj || obj instanceof MinimalModuleVersionIdentifier o
|
||||
&& Objects.equals(this.group, o.group)
|
||||
&& Objects.equals(this.name, o.name)
|
||||
&& Objects.equals(this.version, o.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(group, name, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MinimalModuleVersionIdentifier[" +
|
||||
"group=" + group + ", " +
|
||||
"name=" + name + ", " +
|
||||
"version=" + version + ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
import static net.minecraftforge.forge.tasks.Util.getArtifacts
|
||||
import static net.minecraftforge.forge.tasks.Util.iso8601Now
|
||||
|
||||
abstract class LauncherJson extends DefaultTask {
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||
|
||||
LauncherJson() {
|
||||
output.convention(project.layout.buildDirectory.file('libs/version.json'))
|
||||
|
||||
dependsOn(project.tasks.universalJar)
|
||||
input.from(project.tasks.universalJar.archiveFile)
|
||||
input.from(project.configurations.installer)
|
||||
configure {
|
||||
def mc = project.rootProject.ext.MC_VERSION
|
||||
def forge = project.rootProject.ext.FORGE_VERSION
|
||||
def timestamp = iso8601Now()
|
||||
json.putAll([
|
||||
_comment: [
|
||||
"Please do not automate the download and installation of Forge.",
|
||||
"Our efforts are supported by ads from the download page.",
|
||||
"If you MUST automate this, please consider supporting the project through https://www.patreon.com/LexManos/"
|
||||
],
|
||||
id: "$mc-$project.name-$forge",
|
||||
time: timestamp,
|
||||
releaseTime: timestamp,
|
||||
inheritsFrom: mc,
|
||||
type: 'release',
|
||||
logging: [:],
|
||||
mainClass: '',
|
||||
libraries: []
|
||||
] as LinkedHashMap)
|
||||
|
||||
[
|
||||
project.tasks.universalJar
|
||||
].forEach { packed ->
|
||||
dependsOn(packed)
|
||||
input.from packed.archiveFile
|
||||
}
|
||||
|
||||
def patched = project.tasks.applyClientBinPatches
|
||||
dependsOn(patched)
|
||||
input.from patched.output
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
var packed = (AbstractArchiveTask) project.tasks.universalJar
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
json.libraries.add([
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "https://maven.minecraftforge.net/$info.path",
|
||||
sha1: packed.archiveFile.get().asFile.sha1(),
|
||||
size: packed.archiveFile.get().asFile.length()
|
||||
]
|
||||
]
|
||||
])
|
||||
|
||||
var classifier = 'client'
|
||||
var genned = project.tasks.applyClientBinPatches
|
||||
info = Util.getMavenInfoFromTask(genned, classifier)
|
||||
json.libraries.add([
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "",
|
||||
sha1: genned.output.get().asFile.sha1(),
|
||||
size: genned.output.get().asFile.length()
|
||||
]
|
||||
]
|
||||
])
|
||||
|
||||
json.libraries.addAll(getArtifacts(project.configurations.installer).values())
|
||||
Files.writeString(output.get().asFile.toPath(), new JsonBuilder(json).toPrettyString())
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
@CompileStatic
|
||||
abstract class MergeJars extends DefaultTask {
|
||||
MergeJars() {
|
||||
output.convention(project.layout.buildDirectory.dir(name).map { it.file('output.jar') })
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void run() {
|
||||
def jars = inputJars.files
|
||||
|
||||
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(output.get().asFile))) {
|
||||
for (def jar : jars) {
|
||||
try (ZipInputStream zin = new ZipInputStream(new FileInputStream(jar))) {
|
||||
ZipEntry entry
|
||||
while ((entry = zin.getNextEntry()) !== null) {
|
||||
ZipEntry _new = new ZipEntry(entry.getName())
|
||||
_new.setTime(0) //SHOULD be the same time as the main entry, but NOOOO _new.setTime(entry.getTime()) throws DateTimeException, so you get 0, screw you!
|
||||
zout.putNextEntry(_new)
|
||||
IOUtils.copy(zin, zout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@InputFiles
|
||||
abstract ConfigurableFileCollection getInputJars()
|
||||
|
||||
@OutputFile
|
||||
abstract RegularFileProperty getOutput()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.api.tasks.Optional
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class ObjectTarget implements Comparable<ObjectTarget> {
|
||||
@Input
|
||||
String owner
|
||||
|
||||
@Input
|
||||
String name
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
String desc
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
if (desc == null)
|
||||
return owner + '.' + name
|
||||
return owner + '.' + name + desc
|
||||
}
|
||||
|
||||
@Override
|
||||
int compareTo(ObjectTarget o) {
|
||||
return toString() <=> o.toString()
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
abstract class SetupCheckJarCompatibility extends DefaultTask {
|
||||
SetupCheckJarCompatibility() {
|
||||
group = 'jar compatibility'
|
||||
onlyIf {
|
||||
inputVersion.getOrNull() !== null
|
||||
}
|
||||
outputs.upToDateWhen { false } // Never up to date, because this setup task should always run
|
||||
|
||||
baseBinPatchesOutput.convention(project.layout.buildDirectory.dir(name).map { it.file('joined.lzma') })
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void run() {
|
||||
def inputVersion = inputVersion.get()
|
||||
|
||||
def baseForgeUserdev = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-userdev.jar") }.get().asFile
|
||||
project.rootProject.extensions.download.run {
|
||||
src "https://maven.minecraftforge.net/net/minecraftforge/forge/${inputVersion}/forge-${inputVersion}-userdev.jar"
|
||||
dest baseForgeUserdev
|
||||
}
|
||||
|
||||
def joinedLzma = project.zipTree(baseForgeUserdev).matching { it.include('joined.lzma') }.singleFile
|
||||
|
||||
Files.copy(joinedLzma.toPath(), baseBinPatchesOutput.get().asFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
abstract Property<String> getInputVersion()
|
||||
|
||||
@OutputFile
|
||||
abstract RegularFileProperty getBaseBinPatchesOutput()
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import groovy.transform.CompileStatic
|
||||
import org.eclipse.jgit.api.Git
|
||||
|
||||
import javax.annotation.Nullable
|
||||
import java.util.stream.Collectors
|
||||
|
||||
@CompileStatic
|
||||
class TeamcityRequests {
|
||||
public static final Gson GSON = new Gson()
|
||||
|
||||
@Nullable
|
||||
static <T> T jsonRequest(TypeToken<T> clazz, String url) throws Exception {
|
||||
final HttpURLConnection conn = (HttpURLConnection) URI.create(url).toURL().openConnection()
|
||||
conn.setRequestProperty('Accept', 'application/json')
|
||||
conn.setReadTimeout(5 * 1000)
|
||||
conn.setConnectTimeout(5 * 1000)
|
||||
conn.connect()
|
||||
|
||||
if (conn.responseCode !== 200) {
|
||||
return null
|
||||
}
|
||||
|
||||
try (final InputStream is = conn.getInputStream()) {
|
||||
GSON.fromJson(new InputStreamReader(is), clazz.getType())
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static Map<String, Build> buildsByCommit() throws IOException {
|
||||
final Map<String, Build> builds = [:]
|
||||
jsonRequest(new TypeToken<Builds>() {}, 'https://teamcity.minecraftforge.net/guestAuth/app/rest/builds?fields=build:(revisions,number)&locator=buildType:(id:MinecraftForge_MinecraftForge_MinecraftForge_MinecraftForge__Build),defaultFilter:false,count:300,status:SUCCESS')
|
||||
?.build?.forEach {
|
||||
it.revisions.revision.each { rev -> builds[rev.version] = it }
|
||||
}
|
||||
return builds
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String attemptFindBase(File gitPath) {
|
||||
try (final git = Git.open(gitPath)) {
|
||||
final Map<String, Build> buildByCommit = buildsByCommit()
|
||||
for (final commit in git.log().setMaxCount(100).call()) {
|
||||
// Find the first commit which was built on CI
|
||||
final build = buildByCommit[commit.id.name]
|
||||
if (build) {
|
||||
return build.number
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return null
|
||||
}
|
||||
|
||||
static final class Builds {
|
||||
public List<Build> build
|
||||
}
|
||||
|
||||
static final class Build {
|
||||
public String number
|
||||
public Revisions revisions
|
||||
}
|
||||
|
||||
static final class Revisions {
|
||||
public int count
|
||||
public List<Revision> revision
|
||||
}
|
||||
|
||||
static final class Revision {
|
||||
public String version
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.json.JsonSlurper
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.SimpleType
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpRequest
|
||||
import java.net.http.HttpResponse
|
||||
import java.security.MessageDigest
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Semaphore
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
final class Util {
|
||||
public static final int ASM_LEVEL = Opcodes.ASM9
|
||||
private static final HttpClient HTTP = HttpClient.newBuilder().build()
|
||||
|
||||
static void init() {
|
||||
File.metaClass.sha1 = { ->
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
delegate.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
File.metaClass.getSha1 = { !delegate.exists() ? null : delegate.sha1() }
|
||||
File.metaClass.sha256 = { ->
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-256')
|
||||
delegate.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
File.metaClass.getSha256 = { !delegate.exists() ? null : delegate.sha256() }
|
||||
|
||||
File.metaClass.json = { -> new JsonSlurper().parseText(delegate.text) }
|
||||
File.metaClass.getJson = { return delegate.exists() ? new JsonSlurper().parse(delegate) : [:] }
|
||||
File.metaClass.setJson = { json -> delegate.text = new JsonBuilder(json).toPrettyString() }
|
||||
|
||||
Date.metaClass.iso8601 = { ->
|
||||
var format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
var result = format.format(delegate)
|
||||
return result[0..21] + ':' + result[22..-1]
|
||||
}
|
||||
|
||||
String.metaClass.rsplit = { String del, int limit = -1 ->
|
||||
var lst = new ArrayList<String>()
|
||||
int x = 0
|
||||
int idx
|
||||
String tmp = delegate
|
||||
while ((idx = tmp.lastIndexOf(del)) != -1 && (limit === -1 || x++ < limit)) {
|
||||
lst.add(0, tmp.substring(idx + del.length(), tmp.length()))
|
||||
tmp = tmp.substring(0, idx)
|
||||
}
|
||||
lst.add(0, tmp)
|
||||
return lst
|
||||
}
|
||||
}
|
||||
|
||||
static String[] getClasspath(Project project, Map libs, String artifact) {
|
||||
def ret = []
|
||||
artifactTree(project, artifact).each { key, lib ->
|
||||
libs[lib.name] = lib
|
||||
if (lib.name != artifact)
|
||||
ret.add(lib.name)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static Map getArtifacts(Configuration config) {
|
||||
var ret = [:]
|
||||
var semaphore = new Semaphore(1, true)
|
||||
config.resolvedConfiguration.resolvedArtifacts.parallelStream().forEachOrdered(dep -> {
|
||||
var info = getMavenInfoFromDep(dep)
|
||||
var domain = 'libraries.minecraft.net'
|
||||
var url = "https://$domain/$info.path"
|
||||
if (!checkExists(url))
|
||||
url.values[0] = 'maven.minecraftforge.net'
|
||||
|
||||
var sha1 = sha1(dep.file)
|
||||
|
||||
semaphore.acquire()
|
||||
ret[info.key] = [
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: url.toString(),
|
||||
sha1: sha1,
|
||||
size: dep.file.length()
|
||||
]
|
||||
]
|
||||
]
|
||||
semaphore.release()
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromDep(ResolvedArtifact dep) {
|
||||
return getMavenInfoFromMap([
|
||||
group: dep.moduleVersion.id.group,
|
||||
name: dep.moduleVersion.id.name,
|
||||
version: dep.moduleVersion.id.version,
|
||||
classifier: dep.classifier,
|
||||
extension: dep.extension
|
||||
])
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromTask(AbstractArchiveTask task) {
|
||||
return getMavenInfoFromMap([
|
||||
group: task.project.group.toString(),
|
||||
name: task.project.name,
|
||||
version: task.project.version.toString(),
|
||||
classifier: task.archiveClassifier.get(),
|
||||
extension: task.archiveExtension.get()
|
||||
])
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromTask(Task task, String classifier) {
|
||||
return getMavenInfoFromMap([
|
||||
group: task.project.group.toString(),
|
||||
name: task.project.name,
|
||||
version: task.project.version.toString(),
|
||||
classifier: classifier,
|
||||
extension: 'jar'
|
||||
])
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static Map getMavenInfoFromMap(Map<String, String> art) {
|
||||
var key = "$art.group:$art.name"
|
||||
var name = "$art.group:$art.name:$art.version"
|
||||
var path = "${art.group.replace('.', '/')}/$art.name/$art.version/$art.name-$art.version"
|
||||
if (art.classifier !== null) {
|
||||
name += ":$art.classifier"
|
||||
path += "-$art.classifier"
|
||||
}
|
||||
if ('jar' != art.extension) {
|
||||
name += "@$art.extension"
|
||||
path += ".$art.extension"
|
||||
} else {
|
||||
path += ".jar"
|
||||
}
|
||||
return [
|
||||
key: key.toString(),
|
||||
name: name.toString(),
|
||||
path: path.toString(),
|
||||
art: art
|
||||
]
|
||||
}
|
||||
|
||||
static String iso8601Now() { new Date().iso8601() }
|
||||
|
||||
@CompileStatic
|
||||
static String sha1(File file) {
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
file.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static String toHex(byte bite) {
|
||||
return String.format('%02x', bite)
|
||||
}
|
||||
|
||||
private static Map artifactTree(Project project, String artifact, boolean transitive = true) {
|
||||
if (!project.ext.has('tree_resolver'))
|
||||
project.ext.tree_resolver = 1
|
||||
def cfg = project.configurations.create('tree_resolver_' + project.ext.tree_resolver++)
|
||||
cfg.transitive = transitive
|
||||
def dep = project.dependencies.create(artifact)
|
||||
cfg.dependencies.add(dep)
|
||||
def files = cfg.resolve()
|
||||
return getArtifacts(cfg)
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static boolean checkExists(String url) {
|
||||
try {
|
||||
return HTTP.send(HttpRequest.newBuilder(new URI(url))
|
||||
.method('HEAD', HttpRequest.BodyPublishers.noBody()).build(), HttpResponse.BodyHandlers.discarding()
|
||||
).statusCode() === 200
|
||||
} catch (Exception e) {
|
||||
if (e.toString().contains('unable to find valid certification path to requested target'))
|
||||
throw new RuntimeException("Failed to connect to $url: Missing certificate root authority, try updating Java")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
static String getLatestForgeVersion(String mcVersion) {
|
||||
final json = new JsonSlurper().parseText(new URL('https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json').getText('UTF-8'))
|
||||
final ver = json.promos["$mcVersion-latest"]
|
||||
ver === null ? null : (mcVersion + '-' + ver)
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
static void processClassNodes(File file, @ClosureParams(value = SimpleType, options = 'org.objectweb.asm.tree.ClassNode') Closure process) {
|
||||
file.withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) !== null) {
|
||||
if (zein.name.endsWith('.class')) {
|
||||
var node = new ClassNode(ASM_LEVEL)
|
||||
new ClassReader(zin).accept(node, 0)
|
||||
process(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import net.minecraftforge.srgutils.MinecraftVersion
|
||||
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.InputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.objectweb.asm.tree.AnnotationNode
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
|
||||
abstract class ValidateDeprecations extends DefaultTask {
|
||||
@InputFile
|
||||
abstract RegularFileProperty getInput()
|
||||
|
||||
@Input
|
||||
abstract Property<String> getMcVersion()
|
||||
|
||||
ValidateDeprecations() {
|
||||
this.onlyIf { !System.env.TEAMCITY_VERSION }
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
var mcVer = MinecraftVersion.from(mcVersion.get())
|
||||
List<String> errors = []
|
||||
|
||||
Util.processClassNodes(input.get().asFile) {
|
||||
processNode(mcVer, errors, it)
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
errors.forEach {
|
||||
this.logger.error("Deprecated ${it[0]} is marked for removal in ${it[1]} but is not yet removed")
|
||||
}
|
||||
throw new IllegalStateException("Found deprecated members marked for removal but not yet removed in ${mcVer}; see log for details")
|
||||
}
|
||||
}
|
||||
|
||||
protected processNode(MinecraftVersion mcVer, List<String> errors, ClassNode node) {
|
||||
node.visibleAnnotations?.each { annotation ->
|
||||
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
|
||||
"class ${node.name}"
|
||||
}
|
||||
}
|
||||
node.fields?.each { field ->
|
||||
field.visibleAnnotations?.each { annotation ->
|
||||
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
|
||||
"field ${node.name}#${field.name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
node.methods?.each { method ->
|
||||
method.visibleAnnotations?.each { annotation ->
|
||||
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
|
||||
"method ${node.name}#${method.name}${method.desc}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processAnnotations(AnnotationNode annotation, MinecraftVersion mcVer, List<String> errors, Closure<String> context) {
|
||||
def values = annotation.values
|
||||
if (values === null)
|
||||
return
|
||||
int forRemoval = values.indexOf('forRemoval')
|
||||
int since = values.indexOf('since')
|
||||
if (annotation.desc == 'Ljava/lang/Deprecated;' && forRemoval !== -1 && since !== -1 && values.size() >= 4 && values[forRemoval + 1] === true) {
|
||||
def oldVersion = MinecraftVersion.from(values[since + 1])
|
||||
int[] split = ValidateDeprecations.splitDots(oldVersion.toString())
|
||||
if (split.length < 2)
|
||||
return
|
||||
def removeVersion = MinecraftVersion.from("${split[0]}.${split[1] + 1}")
|
||||
if (removeVersion <= mcVer)
|
||||
errors.add([context(), removeVersion])
|
||||
}
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static int[] splitDots(String version) {
|
||||
String[] pts = version.split('\\.')
|
||||
int[] values = new int[pts.length]
|
||||
for (int x = 0; x < pts.length; x++)
|
||||
values[x] = Integer.parseInt(pts[x])
|
||||
return values
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.TupleConstructor
|
||||
import net.minecraftforge.forge.tasks.InheritanceData
|
||||
import net.minecraftforge.srgutils.IMappingFile
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.objectweb.asm.Opcodes
|
||||
|
||||
@CompileStatic
|
||||
abstract class CheckATs extends CheckTask {
|
||||
|
||||
@InputFile abstract RegularFileProperty getInheritance()
|
||||
@InputFiles abstract ConfigurableFileCollection getAts()
|
||||
|
||||
@Override
|
||||
void check(Reporter reporter, boolean fix) {
|
||||
final inheritance = InheritanceData.parse(this.inheritance.get().asFile)
|
||||
|
||||
ats.each {
|
||||
final lines = process(it, reporter, inheritance)
|
||||
if (fix) {
|
||||
it.text = joinBack(lines, inheritance).join('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeMap<String, ATParser.Entry> process(File file, Reporter reporter, Map<String, InheritanceData> inheritance) {
|
||||
final TreeMap<String, ATParser.Entry> lines = ATParser.parse(file.readLines(), reporter)
|
||||
final Map<String, ATParser.Entry> constructorGroups = [:]
|
||||
|
||||
final itr = lines.entrySet().iterator()
|
||||
final toRemove = []
|
||||
while (itr.hasNext()) {
|
||||
final next = itr.next()
|
||||
String key = next.key
|
||||
final entry = next.value
|
||||
if (entry === null) continue
|
||||
|
||||
final binaryName = entry.cls.replaceAll('\\.', '/')
|
||||
|
||||
// Process Groups, this will remove any entries outside the group that is covered by the group
|
||||
if (entry.group) {
|
||||
final jcls = inheritance[binaryName]
|
||||
if (jcls === null) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid group: $key")
|
||||
} else if ('*' == entry.desc) {
|
||||
if (!jcls.fields) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid group, class has no fields: $key")
|
||||
} else {
|
||||
jcls.fields.each { field, value ->
|
||||
final fkey = entry.cls + ' ' + field
|
||||
if (accessLevel(value.access) < accessStr(entry.modifier)) {
|
||||
if (lines.containsKey(fkey)) {
|
||||
toRemove.add(fkey)
|
||||
} else if (!entry.existing.contains(fkey)) {
|
||||
reporter.report("Missing group entry: $fkey")
|
||||
}
|
||||
entry.children.add(fkey)
|
||||
} else if (lines.containsKey(fkey)) {
|
||||
toRemove.add(fkey)
|
||||
reporter.report("Found invalid group entry: $fkey")
|
||||
}
|
||||
}
|
||||
entry.existing.findAll { it !in entry.children }.each { println('Removed: ' + it) }
|
||||
}
|
||||
} else if ('*()' == entry.desc) {
|
||||
if (!jcls.methods) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid group, class has no methods: $key")
|
||||
} else {
|
||||
jcls.methods.each { mtd, value ->
|
||||
if (mtd.startsWith('<clinit>') || mtd.startsWith('lambda$')) return
|
||||
key = entry.cls + ' ' + mtd.replace(' ', '')
|
||||
if (accessLevel(value.access) < accessStr(entry.modifier)) {
|
||||
if (lines.containsKey(key)) {
|
||||
toRemove.add(key)
|
||||
} else if (!entry.existing.contains(key)) {
|
||||
reporter.report("Missing group entry: $key")
|
||||
}
|
||||
entry.children.add(key)
|
||||
} else if (lines.containsKey(key)) {
|
||||
toRemove.add(key)
|
||||
reporter.report("Found invalid group entry: $key")
|
||||
}
|
||||
}
|
||||
entry.existing.findAll { it !in entry.children }.each { println('Removed: ' + it) }
|
||||
}
|
||||
} else if ('<init>' == entry.desc) { //Make all public non-abstract subclasses
|
||||
constructorGroups.put(binaryName, entry)
|
||||
}
|
||||
}
|
||||
|
||||
// Process normal lines, remove invalid and remove narrowing
|
||||
else {
|
||||
def jcls = inheritance.get(binaryName)
|
||||
if (jcls === null) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid: $key")
|
||||
} else if (entry.desc == '') {
|
||||
if (accessLevel(jcls.access) > accessStr(entry.modifier) && (entry.comment === null || !entry.comment.startsWith('#force '))) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid Narrowing: $key")
|
||||
}
|
||||
} else if (!entry.desc.contains('(')) {
|
||||
if (!jcls.fields || !jcls.fields.containsKey(entry.desc)) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid: $key")
|
||||
} else {
|
||||
final value = jcls.fields[entry.desc]
|
||||
if (accessLevel(value.access) > accessStr(entry.modifier) && (entry.comment === null || !entry.comment.startsWith('#force '))) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid Narrowing: $key - ${entry.comment}")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final jdesc = entry.desc.replace('(', ' (')
|
||||
if (!jcls.methods || !jcls.methods.containsKey(jdesc)) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid: $key")
|
||||
} else {
|
||||
final value = jcls.methods[jdesc]
|
||||
if (accessLevel(value.access) > accessStr(entry.modifier) && (entry.comment === null || !entry.comment.startsWith('#force '))) {
|
||||
itr.remove()
|
||||
reporter.report("Invalid Narrowing: $key")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inheritance.each { tcls, value ->
|
||||
if (!value.methods || ((value.access & Opcodes.ACC_ABSTRACT) !== 0)) return
|
||||
String parent = tcls
|
||||
while (parent !== null) {
|
||||
constructorGroups[parent]?.tap { entry ->
|
||||
value.methods.each { mtd, v ->
|
||||
if (mtd.startsWith('<init>')) {
|
||||
final child = tcls.replaceAll('/', '\\.') + ' ' + mtd.replace(' ', '')
|
||||
if (accessLevel(v.access) < 3) {
|
||||
if (lines.containsKey(child)) {
|
||||
toRemove.add(child)
|
||||
} else if (child !in entry.existing) {
|
||||
reporter.report("Missing group entry: $child")
|
||||
}
|
||||
entry.children.add(child)
|
||||
} else if (lines.containsKey(child)) {
|
||||
toRemove.add(child)
|
||||
reporter.report("Found invalid group entry: $child")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parent = inheritance[parent]?.superName
|
||||
}
|
||||
}
|
||||
constructorGroups.values().each { entry -> entry.existing.findAll { it !in entry.children }.each{ reporter.report("Found invalid group entry: $it") } }
|
||||
|
||||
toRemove.each(lines.&remove)
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
private static List<String> joinBack(TreeMap<String, ATParser.Entry> lines, Map<String, InheritanceData> inheritance) {
|
||||
final data = [] as List<String>
|
||||
lines.each { key, value ->
|
||||
if (!value.group) {
|
||||
def comment = null //value.comment
|
||||
data.add(value.modifier + ' ' + key + (comment ? ' ' + comment : ''))
|
||||
} else {
|
||||
data.add(('#group ' + value.modifier + ' ' + key + ' ' + (value.comment ?: '')).trim())
|
||||
value.children.each {
|
||||
final line = value.modifier + ' ' + it
|
||||
final entry = ATParser.parseEntry(line)
|
||||
final comment = null //entry.comment
|
||||
data.add(line + (comment ? ' ' + comment : ''))
|
||||
}
|
||||
data.add('#endgroup')
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
static int accessStr(String access) {
|
||||
if (access.endsWith('-f') || access.endsWith('+f')) return 4
|
||||
switch (access.toLowerCase()) {
|
||||
case 'public': return 3
|
||||
case 'protected': return 2
|
||||
case 'default': return 1
|
||||
case 'private': return 0
|
||||
default: return -1
|
||||
}
|
||||
}
|
||||
|
||||
static int accessLevel(int access) {
|
||||
if ((access & Opcodes.ACC_PUBLIC) !== 0) return 3
|
||||
if ((access & Opcodes.ACC_PROTECTED) !== 0) return 2
|
||||
if ((access & Opcodes.ACC_PRIVATE) !== 0) return 0
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
class ATParser {
|
||||
static TreeMap<String, Entry> parse(List<String> lines, CheckTask.Reporter reporter) {
|
||||
TreeMap<String, Entry> outLines = new TreeMap<>()
|
||||
Entry group = null
|
||||
for (final line : lines) {
|
||||
if (line.isEmpty()) continue
|
||||
if (line.startsWith('#group ')) {
|
||||
final entry = parseEntry(line.substring(7))
|
||||
|
||||
if (entry.desc != '*' && entry.desc != '*()' && entry.desc != '<init>') {
|
||||
reporter.report("Invalid group: $line", false)
|
||||
}
|
||||
|
||||
entry.group = true
|
||||
entry.children = []
|
||||
entry.existing = []
|
||||
|
||||
group = entry
|
||||
|
||||
if (outLines.containsKey(entry.key)) {
|
||||
reporter.report("Duplicate group: $line", false)
|
||||
}
|
||||
|
||||
outLines[entry.key] = group
|
||||
} else if (group !== null) {
|
||||
if (line.startsWith('#endgroup')) {
|
||||
group = null
|
||||
} else {
|
||||
final key = parseEntry(line).key
|
||||
group.existing.add(key)
|
||||
}
|
||||
} else if (line.startsWith('#endgroup')) {
|
||||
reporter.report("Invalid group ending: $line", false)
|
||||
} else if (line.startsWith('#')) {
|
||||
//Nom
|
||||
} else {
|
||||
final entry = parseEntry(line)
|
||||
if (outLines.containsKey(entry.key)) {
|
||||
reporter.report("Found duplicate: $line")
|
||||
continue
|
||||
}
|
||||
outLines[entry.key] = entry
|
||||
}
|
||||
}
|
||||
return outLines
|
||||
}
|
||||
|
||||
static Entry parseEntry(String line) {
|
||||
final idx = line.indexOf('#')
|
||||
final String comment = idx === -1 ? null : line.substring(idx)
|
||||
if (idx !== -1) line = line.substring(0, idx - 1)
|
||||
final data = (line.trim() + ' ').split(' ', -1)
|
||||
data[1] = data[1].replaceAll('/', '.') // Convert to Source names, internal names are fine by spec, but not supported by old AST based AT implementations.
|
||||
new Entry(data[0], data[1], data[2], comment)
|
||||
}
|
||||
|
||||
@TupleConstructor
|
||||
static final class Entry {
|
||||
String modifier, cls, desc, comment
|
||||
|
||||
Set<String> existing
|
||||
TreeSet<String> children
|
||||
boolean group = false
|
||||
|
||||
@Lazy
|
||||
String key = {cls + (desc.isEmpty() ? '' : ' ' + desc)}()
|
||||
|
||||
Object getAt(String key) {
|
||||
return getProperty(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import net.minecraftforge.forge.tasks.Util
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Type
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
abstract class CheckExcs extends CheckTask {
|
||||
|
||||
@InputFile abstract RegularFileProperty getBinary()
|
||||
@InputFiles abstract ConfigurableFileCollection getExcs()
|
||||
|
||||
@Override
|
||||
void check(Reporter reporter, boolean fix) {
|
||||
final Set<String> known = []
|
||||
collectKnown(known)
|
||||
|
||||
excs.each { f ->
|
||||
final lines = []
|
||||
f.eachLine { line ->
|
||||
int idx = line.indexOf('#')
|
||||
if (idx === 0 || line.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (idx !== -1) line = line.substring(0, idx - 1)
|
||||
|
||||
if (!line.contains('=')) {
|
||||
reporter.report("Invalid: $line")
|
||||
return
|
||||
}
|
||||
|
||||
def (String key, String value) = line.split('=', 2)
|
||||
if (!known.contains(key)) {
|
||||
reporter.report("Unknown: $line")
|
||||
return
|
||||
}
|
||||
|
||||
String desc = key.split('\\.', 2)[1]
|
||||
if (!desc.contains('(')) {
|
||||
reporter.report("Invalid: $line")
|
||||
return
|
||||
}
|
||||
desc = '(' + desc.split('\\(', 2)[1]
|
||||
|
||||
def (exceptions, String args) = value.contains('|') ? value.split('|', 2) : [value, '']
|
||||
|
||||
if (args.split(',').length !== Type.getArgumentTypes(desc).length) {
|
||||
reporter.report("Invalid: $line")
|
||||
return
|
||||
}
|
||||
lines.add(line)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (fix) f.text = lines.sort().join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
private void collectKnown(Collection<String> known) {
|
||||
binary.get().asFile.withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
final visitor = new ClassVisitor(Util.ASM_LEVEL) {
|
||||
private String cls
|
||||
@Override
|
||||
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
this.cls = name
|
||||
}
|
||||
|
||||
@Override
|
||||
MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
known.add(this.cls + '.' + name + descriptor)
|
||||
super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
}
|
||||
}
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) !== null) {
|
||||
if (zein.name.endsWith('.class')) {
|
||||
ClassReader reader = new ClassReader(zin)
|
||||
reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
enum CheckMode {
|
||||
CHECK,
|
||||
FIX
|
||||
|
||||
CheckMode() {}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.Optional
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@CompileStatic
|
||||
abstract class CheckPatches extends CheckTask {
|
||||
|
||||
private static final Pattern HUNK_START_PATTERN = Pattern.compile('^@@ -[0-9,]* \\+[0-9,_]* @@$')
|
||||
private static final Pattern WHITESPACE_PATTERN = Pattern.compile('^[+\\-]\\s*$')
|
||||
private static final Pattern IMPORT_PATTERN = Pattern.compile('^[+\\-]\\s*import.*')
|
||||
private static final Pattern FIELD_PATTERN = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final)?([^=;]*)(=.*)?;\\s*$')
|
||||
private static final Pattern METHOD_PATTERN = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final)?([^(]*)[(]([^)]*)?[)]\\s*[{]\\s*$')
|
||||
private static final Pattern CLASS_PATTERN = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final[\\s]*)?(class|interface)([^{]*)[{]\\s*$')
|
||||
private static final Map<String, Integer> ACCESS_MAP = [private: 0, protected: 2, public: 3].tap { it.put(null, 1) }
|
||||
|
||||
@InputDirectory abstract DirectoryProperty getPatchDir()
|
||||
@Input @Optional abstract ListProperty<String> getPatchesWithS2SArtifact()
|
||||
|
||||
@Override
|
||||
void check(Reporter reporter, boolean fix) {
|
||||
final patchDir = getPatchDir().get().asFile.toPath()
|
||||
Files.walk(patchDir).withCloseable {
|
||||
it.filter(Files.&isRegularFile).forEach { path ->
|
||||
final String relativeName = patchDir.relativize(path).toString()
|
||||
verifyPatch(path, reporter, fix, relativeName, patchesWithS2SArtifact.get().contains(relativeName.replace('\\', '/')))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean accessChange(String previous, String current) {
|
||||
//return ACCESS_MAP[previous] < ACCESS_MAP[current]
|
||||
return previous != current
|
||||
}
|
||||
|
||||
void verifyPatch(Path patch, Reporter reporter, boolean fix, String patchPath, boolean hasS2SArtifact) {
|
||||
int oldFixedErrors = reporter.fixed.size()
|
||||
|
||||
final lines = Files.readAllLines(patch)
|
||||
|
||||
int hunksStart = 0
|
||||
boolean onlyWhiteSpace = false
|
||||
|
||||
final List<String> newLines = []
|
||||
|
||||
// First two lines are file name ++/-- and we do not care
|
||||
newLines.add(lines[0] + '\n')
|
||||
newLines.add(lines[1] + '\n')
|
||||
|
||||
int i
|
||||
for (i = 2; i < lines.size(); ++i) {
|
||||
def line = lines[i]
|
||||
newLines.add(line + '\n')
|
||||
|
||||
if (HUNK_START_PATTERN.matcher(line).find()) {
|
||||
if (onlyWhiteSpace) {
|
||||
if (!hasS2SArtifact)
|
||||
reporter.report("Patch contains only white space hunk starting at line ${hunksStart + 1}, file: $patchPath")
|
||||
int toRemove = i - hunksStart
|
||||
while (toRemove-- > 0)
|
||||
newLines.remove(newLines.size() - 1)
|
||||
}
|
||||
hunksStart = i
|
||||
onlyWhiteSpace = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (line.startsWithAny('+','-')) {
|
||||
def prefixChange = false
|
||||
def prevLine = lines[i - 1]
|
||||
|
||||
if (line.charAt(0) == (char)'+' && prevLine.charAt(0) == (char)'-') {
|
||||
def prevTrim = prevLine.substring(1).replaceAll("\\s", "")
|
||||
def currTrim = line.substring(1).replaceAll("\\s", "")
|
||||
|
||||
if (prevTrim == currTrim) {
|
||||
prefixChange = true
|
||||
}
|
||||
|
||||
def pMatcher = FIELD_PATTERN.matcher(prevLine)
|
||||
def cMatcher = FIELD_PATTERN.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // = ...
|
||||
pMatcher.group(5) == cMatcher.group(5) && // field name
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
|
||||
}
|
||||
|
||||
pMatcher = METHOD_PATTERN.matcher(prevLine)
|
||||
cMatcher = METHOD_PATTERN.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // params
|
||||
pMatcher.group(5) == cMatcher.group(5) && // <T> void name
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
|
||||
}
|
||||
|
||||
pMatcher = CLASS_PATTERN.matcher(prevLine)
|
||||
cMatcher = CLASS_PATTERN.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // ClassName<> extends ...
|
||||
pMatcher.group(5) == cMatcher.group(5) && // class | interface
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
|
||||
}
|
||||
}
|
||||
|
||||
if (line.charAt(0) == (char)'-' && i + 1 < lines.size()) {
|
||||
final nextLine = lines[i + 1]
|
||||
if (nextLine.charAt(0) == (char)'+') {
|
||||
final nextTrim = nextLine.substring(1).replaceAll("\\s", "")
|
||||
final currTrim = line.substring(1).replaceAll("\\s", "")
|
||||
|
||||
if (nextTrim == currTrim) {
|
||||
prefixChange = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final isWhiteSpaceChange = WHITESPACE_PATTERN.matcher(line).find()
|
||||
|
||||
if (!prefixChange && !isWhiteSpaceChange) {
|
||||
onlyWhiteSpace = hasS2SArtifact && IMPORT_PATTERN.matcher(line).find()
|
||||
} else if (isWhiteSpaceChange) {
|
||||
final prevLineChange = prevLine.startsWithAny('+','-')
|
||||
final nextLineChange = i + 1 < lines.size() && lines[i + 1].startsWithAny('+','-')
|
||||
|
||||
if (!prevLineChange && !nextLineChange) {
|
||||
reporter.report("Patch contains white space change in valid hunk at line ${i + 1}, file: $patchPath \n$prevLine\n$line\n${lines[i+1]}", false)
|
||||
}
|
||||
}
|
||||
|
||||
if (line.contains('\t')) {
|
||||
reporter.report("Patch contains tabs on line ${i + 1}, file: $patchPath")
|
||||
line = line.replaceAll('\t', ' ')
|
||||
newLines.remove(newLines.size() - 1)
|
||||
newLines.add(line + '\n')
|
||||
}
|
||||
|
||||
if (IMPORT_PATTERN.matcher(line).find() && !hasS2SArtifact) {
|
||||
reporter.report("Patch contains import change on line ${i + 1}, file: $patchPath", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (onlyWhiteSpace) {
|
||||
if (!hasS2SArtifact)
|
||||
reporter.report("Patch contains only white space hunk starting at line ${hunksStart + 1}, file: $patchPath")
|
||||
def toRemove = i - hunksStart;
|
||||
while (toRemove-- > 0)
|
||||
newLines.remove(newLines.size() - 1)
|
||||
}
|
||||
|
||||
if ((reporter.fixed.size() > oldFixedErrors && fix) || hasS2SArtifact) {
|
||||
if (newLines.size() <= 2) {
|
||||
logger.lifecycle("Patch is now empty removing, file: {}", patchPath)
|
||||
Files.delete(patch)
|
||||
}
|
||||
else {
|
||||
if (!hasS2SArtifact)
|
||||
logger.lifecycle("*** Updating patch file. Please run setup then genPatches again. ***")
|
||||
Files.newBufferedWriter(patch).withCloseable {
|
||||
newLines.each { l -> it.write(l) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import net.minecraftforge.forge.tasks.Annotatable
|
||||
import net.minecraftforge.forge.tasks.InheritanceData
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
|
||||
@CompileStatic
|
||||
abstract class CheckSAS extends CheckTask {
|
||||
|
||||
@InputFile abstract RegularFileProperty getInheritance()
|
||||
@InputFiles abstract ConfigurableFileCollection getSass()
|
||||
|
||||
@Override
|
||||
void check(Reporter reporter, boolean fix) {
|
||||
final inheritance = InheritanceData.parse(this.inheritance.get().asFile)
|
||||
|
||||
sass.each { f ->
|
||||
final lines = []
|
||||
f.eachLine { line ->
|
||||
if (line[0] == '\t') return // Skip any tabbed lines, those are ones we add
|
||||
final idx = line.indexOf('#')
|
||||
if (idx == 0 || line.isEmpty()) {
|
||||
lines.add(line)
|
||||
return
|
||||
}
|
||||
def comment = idx == -1 ? null : line.substring(idx)
|
||||
if (idx != -1) line = line.substring(0, idx - 1)
|
||||
final spl = (line.trim().replace('(', ' (') + ' ').split(' ', -1)
|
||||
def (String cls, String name, String desc) = [spl[0], spl[1], spl[2]]
|
||||
cls = cls.replaceAll('\\.', '/')
|
||||
|
||||
if (inheritance[cls] === null) {
|
||||
reporter.report("Invalid: $line")
|
||||
} else if (name.isEmpty()) { //Class SAS
|
||||
final toAdd = []
|
||||
final clsSided = isSided(inheritance[cls])
|
||||
boolean sided = clsSided
|
||||
|
||||
/* TODO: MergeTool doesn't do fields
|
||||
if (json[cls]['fields'] != null) {
|
||||
for (entry in json[cls]['fields']) {
|
||||
if (isSided(entry.value)) {
|
||||
sided = true
|
||||
toAdd.add('\t' + cls + ' ' + entry.key)
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
final clsInh = inheritance[cls]
|
||||
if (clsInh.methods) {
|
||||
for (entry in clsInh.methods) {
|
||||
if (isSided(entry.value)) {
|
||||
sided = true
|
||||
toAdd.add('\t' + cls + ' ' + entry.key.replaceAll(' ', ''))
|
||||
findChildMethods(inheritance, cls, entry.key).each { lines.add('\t' + it) }
|
||||
findChildMethods(inheritance, cls, entry.key).each { println(line + ' -- ' + it) }
|
||||
} else if (clsSided) {
|
||||
findChildMethods(inheritance, cls, entry.key).each { lines.add('\t' + it) }
|
||||
findChildMethods(inheritance, cls, entry.key).each { println(line + ' -- ' + it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sided) {
|
||||
lines.add(cls + (comment == null ? '' : ' ' + comment))
|
||||
lines.addAll(toAdd.sort())
|
||||
} else {
|
||||
reporter.report("Invalid: $line")
|
||||
}
|
||||
|
||||
} else if (desc.isEmpty()) { // Fields
|
||||
/* TODO: MergeTool doesn't do fields
|
||||
if (json[cls]['fields'] != null && isSided(json[cls]['fields'][name]))
|
||||
lines.add(cls + ' ' + name + (comment == null ? '' : ' ' + comment))
|
||||
else */
|
||||
reporter.report("Invalid: $line")
|
||||
} else { // Methods
|
||||
final clsInh = inheritance[cls]
|
||||
if (clsInh.methods === null || !isSided(clsInh.methods[name + ' ' + desc]))
|
||||
reporter.report("Invalid: $line")
|
||||
else {
|
||||
lines.add(cls + ' ' + name + desc + (comment == null ? '' : ' ' + comment))
|
||||
findChildMethods(inheritance, cls, name + ' ' + desc).each { println(line + ' -- ' + it) }
|
||||
findChildMethods(inheritance, cls, name + ' ' + desc).each { lines.add('\t' + it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fix) f.text = lines.join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean isSided(Annotatable annotatable) {
|
||||
if (annotatable === null) return false
|
||||
for (ann in annotatable.annotations) {
|
||||
if ('Lnet/minecraftforge/api/distmarker/OnlyIn;' == ann.desc)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
protected static findChildMethods(Map<String, InheritanceData> json, String cls, String desc) {
|
||||
return json.values().findAll{ it.methods !== null && it.methods[desc] !== null && it.methods[desc].override == cls && isSided(it.methods[desc]) }
|
||||
.collect { it.name + ' ' + desc.replace(' ', '') } as TreeSet
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.ThirdParam
|
||||
import net.minecraftforge.forge.tasks.Util
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.TaskContainer
|
||||
import org.gradle.api.tasks.VerificationTask
|
||||
|
||||
@CompileStatic
|
||||
abstract class CheckTask extends DefaultTask implements VerificationTask {
|
||||
@Input
|
||||
abstract Property<CheckMode> getMode()
|
||||
|
||||
private boolean ignoreFailures = false
|
||||
|
||||
@Input
|
||||
@Override
|
||||
boolean getIgnoreFailures() {
|
||||
return ignoreFailures
|
||||
}
|
||||
|
||||
@Override
|
||||
void setIgnoreFailures(boolean ignoreFailures) {
|
||||
this.ignoreFailures = ignoreFailures
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void run() {
|
||||
Util.init()
|
||||
|
||||
boolean doFix = getMode().get() === CheckMode.FIX
|
||||
final Reporter reporter = new Reporter(doFix)
|
||||
check(reporter, doFix)
|
||||
|
||||
if (reporter.messages) {
|
||||
if (getMode().get() === CheckMode.CHECK) {
|
||||
logger.error("Check task '{}' found errors:\n{}", name, reporter.messages.join('\n'))
|
||||
if (!ignoreFailures) {
|
||||
throw new IllegalArgumentException("${reporter.messages.size()} errors were found!")
|
||||
}
|
||||
} else {
|
||||
if (logger.isEnabled(LogLevel.DEBUG)) {
|
||||
logger.warn("Check task '{}' found {} errors and fixed {}:\n{}", name, reporter.messages.size(), reporter.fixed.size(), reporter.fixed.join('\n'))
|
||||
} else {
|
||||
logger.warn("Check task '{}' found {} errors and fixed {}.", name, reporter.messages.size(), reporter.fixed.size())
|
||||
}
|
||||
|
||||
if (reporter.notFixed) {
|
||||
logger.error('{} errors could not be fixed:\n{}', reporter.notFixed.size(), reporter.notFixed.join('\n'))
|
||||
if (!ignoreFailures) {
|
||||
throw new IllegalArgumentException("${reporter.notFixed.size()} errors which cannot be fixed were found!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract void check(Reporter reporter, boolean fix)
|
||||
|
||||
@CompileStatic
|
||||
static final class Reporter {
|
||||
final boolean trackFixed
|
||||
Reporter(boolean trackFixed) {
|
||||
this.trackFixed = trackFixed
|
||||
}
|
||||
|
||||
public final List<String> messages = []
|
||||
|
||||
public final List<String> fixed = []
|
||||
public final List<String> notFixed = []
|
||||
|
||||
void report(String message, boolean canBeFixed = true) {
|
||||
messages.add(message)
|
||||
|
||||
if (trackFixed) {
|
||||
if (canBeFixed) {
|
||||
fixed.add(message)
|
||||
} else {
|
||||
notFixed.add(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static <T extends CheckTask> void registerTask(TaskContainer tasks, String taskName, @DelegatesTo.Target('type') Class<T> clazz,
|
||||
@DelegatesTo(genericTypeIndex = 0, target = 'type')
|
||||
@ClosureParams(ThirdParam.FirstGenericType) Closure configuration) {
|
||||
taskName = taskName.capitalize()
|
||||
tasks.register("check$taskName", clazz) { CheckTask task ->
|
||||
def castedTask = task as T
|
||||
configuration.setDelegate(castedTask)
|
||||
configuration.call(castedTask)
|
||||
castedTask.mode.set(CheckMode.CHECK)
|
||||
castedTask.group = 'checks'
|
||||
}
|
||||
tasks.named('checkAll').configure { it.dependsOn("check$taskName") }
|
||||
|
||||
tasks.register("checkAndFix$taskName", clazz) { CheckTask task ->
|
||||
def castedTask = task as T
|
||||
configuration.setDelegate(castedTask)
|
||||
configuration.call(castedTask)
|
||||
castedTask.mode.set(CheckMode.FIX)
|
||||
castedTask.group = 'checks'
|
||||
}
|
||||
tasks.named('checkAllAndFix').configure { it.dependsOn("checkAndFix$taskName") }
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'net.minecraftforge.gradle.patcher'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':mcp')
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven gradleutils.forgeMaven
|
||||
maven gradleutils.minecraftLibsMaven
|
||||
}
|
||||
|
||||
java.toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
|
||||
dependencies {
|
||||
implementation(libs.forgespi)
|
||||
}
|
||||
|
||||
patcher {
|
||||
parent = project(':mcp')
|
||||
mcVersion = MC_VERSION
|
||||
patchedSrc = file('src/main/java')
|
||||
|
||||
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
|
||||
|
||||
runs {
|
||||
clean_client {
|
||||
client true
|
||||
taskName 'clean_client'
|
||||
ideaModule "${rootProject.name}.${project.name}.main"
|
||||
|
||||
main 'net.minecraft.client.main.Main'
|
||||
workingDirectory project.file('run/client')
|
||||
|
||||
args '--gameDir', '.'
|
||||
args '--version', MC_VERSION
|
||||
args '--assetsDir', downloadAssets.output
|
||||
args '--assetIndex', '{asset_index}'
|
||||
args '--accessToken', '0'
|
||||
}
|
||||
|
||||
clean_server {
|
||||
client false
|
||||
taskName 'clean_server'
|
||||
ideaModule "${rootProject.name}.${project.name}.main"
|
||||
|
||||
main 'net.minecraft.server.Main'
|
||||
workingDirectory project.file('run/server')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
options.warnings = false // Shutup deprecated for removal warnings
|
||||
}
|
||||
|
||||
eclipse.classpath.file.whenMerged {
|
||||
// Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase
|
||||
def src = entries.find { it.path == 'src/main/java' }
|
||||
if (src == null) throw new IllegalStateException("You must run `setup` task before importing")
|
||||
src.entryAttributes['ignore_optional_problems'] = 'true'
|
||||
}
|
||||
|
||||
tasks.named('genPatches').configure {
|
||||
onlyIf { false }
|
||||
}
|
||||
|
||||
tasks.named('extractRangeMap').configure {
|
||||
onlyIf { false }
|
||||
tool = 'net.minecraftforge:Srg2Source:8.1.0:fatjar'
|
||||
}
|
||||
-1021
File diff suppressed because it is too large.
Load diff
@@ -1,89 +0,0 @@
|
||||
import net.minecraftforge.forge.tasks.CleanProperties
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'net.minecraftforge.gradleutils'
|
||||
|
||||
group = 'net.minecraftforge'
|
||||
version = VERSION
|
||||
println("Version: $version")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven gradleutils.forgeMaven
|
||||
maven gradleutils.minecraftLibsMaven
|
||||
//mavenLocal()
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc).configureEach {
|
||||
options.tags = [
|
||||
'apiNote:a:<em>API Note:</em>',
|
||||
'implSpec:a:<em>Implementation Requirements:</em>',
|
||||
'implNote:a:<em>Implementation Note:</em>'
|
||||
]
|
||||
options.addStringOption('Xdoclint:all,-missing', '-public')
|
||||
}
|
||||
|
||||
// We need to write the manifest to the binary file so we have properly versioned packaged at dev time.
|
||||
tasks.register('writeManifest') {
|
||||
doLast {
|
||||
if (plugins.findPlugin('net.minecraftforge.gradle.patcher')) // Forge project
|
||||
universalJar.manifest.writeTo(rootProject.file('src/main/resources/META-INF/MANIFEST.MF'))
|
||||
else
|
||||
jar.manifest.writeTo(project.file('src/main/resources/META-INF/MANIFEST.MF'))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('generateResources') {
|
||||
dependsOn('writeManifest')
|
||||
}
|
||||
|
||||
tasks.named('processResources') {
|
||||
dependsOn(generateResources)
|
||||
}
|
||||
|
||||
// Make sure out manifests get written before compiling the code, IDEA calls this task if you tell it to use the gradle build.
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
dependsOn 'generateResources'
|
||||
dependsOn 'processResources' // Needed because we merge the output of this with the output of the compile task. And gradle detects downstream tasks using the output without a hard dep
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
options.warnings = false // Shutup deprecated for removal warnings
|
||||
options.forkOptions.jvmArgs += '-Xmx6G' // Needed to make compiling faster, and not run out of heap space in some cases.
|
||||
}
|
||||
|
||||
// Merge the resources and classes into the same directory. We'll need to split them at runtime because
|
||||
// Minecraft and Forge are in the same sourceSet as they are inter dependent.. for now..
|
||||
sourceSets.each {
|
||||
def dir = layout.buildDirectory.dir("classes/java/$it.name")
|
||||
it.output.resourcesDir = dir
|
||||
it.java.destinationDirectory = dir
|
||||
}
|
||||
|
||||
tasks.register('copyEclipseSettings') {
|
||||
doLast {
|
||||
rootProject.fileTree('ide/eclipse/template/.settings/').matching { include '**/*.prefs' }.each { file ->
|
||||
def target = project.file('.settings/' + file.name)
|
||||
def temp = new CleanProperties().load(file)
|
||||
def exst = new CleanProperties().load(target)
|
||||
exst.put('eclipse.preferences.version', '1')
|
||||
exst.putAll(temp)
|
||||
exst.store(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: [Gradle][IntelliJ] Auto trigger these tasks on import.
|
||||
eclipse {
|
||||
// Run everytime eclipse builds the code
|
||||
//autoBuildTasks writeManifest
|
||||
// Run when importing the project
|
||||
synchronizationTasks generateResources, copyEclipseSettings, eclipseClasspath, eclipseProject
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
// IntelliJ IDEA does not do this by itself anymore...
|
||||
downloadJavadoc = true
|
||||
downloadSources = true
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[][Download]
|
||||
[][Download]
|
||||
[][Download] [][Discord] [][Patreon]
|
||||
|
||||
Forge is a free, open-source modding API all of your favourite mods use!
|
||||
|
||||
+50
-40
@@ -1,68 +1,78 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
gradleutils.displayName = 'FML'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Modifications to Minecraft to enable mod developers.'
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
api(libs.eventbus)
|
||||
annotationProcessor(libs.eventbus.validator)
|
||||
api libs.eventbus
|
||||
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(libs.commons.io)
|
||||
implementation projects.fmlloader
|
||||
implementation libs.commons.io
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.fmlcore',
|
||||
'FMLModType': 'LIBRARY'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'FML',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FML',
|
||||
'Implementation-Version': '1.0',
|
||||
'Implementation-Vendor': 'Forge Development LLC'
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/')
|
||||
}
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:-unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
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 {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'fmlcore'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Modifactions to Minecraft to enable mod developers.'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,74 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
import org.gradle.api.plugins.jvm.JvmTestSuite
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'jvm-test-suite'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
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
|
||||
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(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
implementation(libs.bundles.lwjgl)
|
||||
implementation('org.slf4j:slf4j-api:1.8.0-beta4')
|
||||
implementation(libs.jopt.simple)
|
||||
testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.2')
|
||||
testImplementation('org.powermock:powermock-core:2.0.9')
|
||||
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.8.2')
|
||||
testRuntimeOnly('org.slf4j:slf4j-jdk14:1.8.0-beta4')
|
||||
testRuntimeOnly("org.lwjgl:lwjgl::$lwjglNatives")
|
||||
testRuntimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives")
|
||||
testRuntimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives")
|
||||
testRuntimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives")
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
implementation projects.fmlloader
|
||||
implementation projects.fmlcore
|
||||
implementation libs.bundles.lwjgl
|
||||
implementation earlyDisplayLibs.slf4j.api
|
||||
implementation libs.jopt.simple
|
||||
}
|
||||
|
||||
tasks.named('test', Test).configure {
|
||||
useJUnitPlatform()
|
||||
// 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.glfw) { classifier lwjglNatives },
|
||||
dependencies.variantOf(earlyDisplayTestLibs.lwjgl.opengl) { classifier lwjglNatives },
|
||||
dependencies.variantOf(earlyDisplayTestLibs.lwjgl.stb) { classifier lwjglNatives }
|
||||
].with { list ->
|
||||
provider { list.collect { it.get() } }
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.earlydisplay',
|
||||
'Forge-Module-Layer': 'boot'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'FML Early Display',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FML Early Display',
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': '1.0'
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/earlydisplay/')
|
||||
testing.suites.named('test', JvmTestSuite) {
|
||||
useJUnitJupiter('5.8.2')
|
||||
|
||||
dependencies {
|
||||
implementation earlyDisplayTestLibs.powermock.core
|
||||
runtimeOnly earlyDisplayLibs.slf4j.jdk14
|
||||
runtimeOnly.bundle lwjglTestLibs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,24 +76,42 @@ tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
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 {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'fmlearlydisplay'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'A pretty looking, but prone to erroring screen displayed during Forge loading.'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -459,7 +459,9 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
this.winWidth = x[0];
|
||||
this.winHeight = y[0];
|
||||
|
||||
// Setting the window position isn't supported on wayland, so check the error here
|
||||
glfwSetWindowPos(window, (vidmode.width() - this.winWidth) / 2 + monitorX, (vidmode.height() - this.winHeight) / 2 + monitorY);
|
||||
handleLastGLFWError();
|
||||
|
||||
// Attempt setting the icon
|
||||
// int[] channels = new int[1];
|
||||
@@ -482,7 +484,10 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
|
||||
// Show the window
|
||||
glfwShowWindow(window);
|
||||
// Getting the window position isn't supported on wayland, so check the error here
|
||||
glfwGetWindowPos(window, x, y);
|
||||
handleLastGLFWError();
|
||||
|
||||
this.winX = x[0];
|
||||
this.winY = y[0];
|
||||
glfwGetFramebufferSize(window, x, y);
|
||||
@@ -491,6 +496,18 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
private static void handleLastGLFWError() {
|
||||
handleLastGLFWError((error, description) -> {
|
||||
if (error == GLFW_FEATURE_UNAVAILABLE) {
|
||||
// suppress window pos errors for unsupported platforms (wayland)
|
||||
LOGGER.debug(String.format("Suppressing GLFW error: [0x%X]%s", error, description));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("GLFW error: [0x%X]%s", error, description));
|
||||
});
|
||||
}
|
||||
|
||||
private void winResize(long window, int width, int height) {
|
||||
if (window == this.window && width != 0 && height != 0) {
|
||||
this.winWidth = width;
|
||||
@@ -648,4 +665,4 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
this.context.elementShader().close();
|
||||
SimpleBufferBuilder.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
+144
-100
@@ -1,69 +1,75 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
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'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias(libs.plugins.apt)
|
||||
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'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
|
||||
configurations.forEach{ it.transitive = false }
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
|
||||
api(libs.bundles.asm) // Needed by all the black magic
|
||||
api(libs.forgespi)
|
||||
api(libs.mergetool.api)
|
||||
api(libs.log4j.api)
|
||||
api(libs.slf4j.api)
|
||||
api(libs.guava)
|
||||
api(libs.gson)
|
||||
api(libs.maven.artifact)
|
||||
api(libs.apache.commons)
|
||||
api(libs.bundles.night.config)
|
||||
api(libs.modlauncher)
|
||||
api(libs.mojang.logging)
|
||||
api(libs.jarjar.selector)
|
||||
api(libs.jarjar.meta)
|
||||
|
||||
implementation(libs.jopt.simple)
|
||||
implementation(libs.securemodules)
|
||||
implementation(libs.accesstransformers)
|
||||
implementation(libs.terminalconsoleappender)
|
||||
implementation(libs.jimfs)
|
||||
implementation(libs.roimfs)
|
||||
|
||||
// Needed because we have a custom log4j plugin, and they removed package scanning and require a data file to be generated
|
||||
implementation(libs.log4j.core)
|
||||
annotationProcessor(libs.bundles.log4j)
|
||||
|
||||
testCompileOnly(libs.jetbrains.annotations)
|
||||
testRuntimeOnly(libs.bootstrap)
|
||||
}
|
||||
gradleutils.displayName = 'FMLLoader'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Modifications to Minecraft to enable mod developers.'
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.fmlloader',
|
||||
'Forge-Module-Layer': 'boot'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'FMLLoader',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FMLLoader',
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': FORGE_VERSION
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/loading/')
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
// TODO [FMLLoader] Figure out a better way to lock transitive dependencies to the explicit versions shipped by the isntaller
|
||||
api(libs.bundles.asm ){ transitive = false } // Needed by all the black magic
|
||||
api(libs.forgespi ){ transitive = false }
|
||||
api(libs.mergetool.api ){ transitive = false }
|
||||
api(libs.log4j.api ){ transitive = false }
|
||||
api(libs.slf4j.api ){ transitive = false }
|
||||
api(libs.guava ){ transitive = false }
|
||||
api(libs.gson ){ transitive = false }
|
||||
api(libs.maven.artifact ){ transitive = false }
|
||||
api(libs.apache.commons ){ transitive = false }
|
||||
api(libs.bundles.night.config){ transitive = false }
|
||||
api(libs.modlauncher ){ transitive = false }
|
||||
api(libs.mojang.logging ){ transitive = false }
|
||||
api(libs.jarjar.selector ){ transitive = false }
|
||||
api(libs.jarjar.meta ){ transitive = false }
|
||||
|
||||
implementation(libs.jopt.simple ){ transitive = false }
|
||||
implementation(libs.securemodules ){ transitive = false }
|
||||
implementation(libs.accesstransformers ){ transitive = false }
|
||||
implementation(libs.terminalconsoleappender){ transitive = false }
|
||||
implementation(libs.jimfs ){ transitive = false }
|
||||
implementation(libs.roimfs ){ transitive = false }
|
||||
|
||||
// Needed because we have a custom log4j plugin, and they removed package scanning and require a data file to be generated
|
||||
implementation(libs.log4j.core ){ transitive = false }
|
||||
annotationProcessor(libs.bundles.log4j){ transitive = false }
|
||||
}
|
||||
|
||||
testing.suites.named('test', JvmTestSuite) {
|
||||
dependencies {
|
||||
compileOnly libs.jetbrains.annotations
|
||||
runtimeOnly libs.bootstrap
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,39 +77,81 @@ tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
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 {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'fmlloader'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Modifactions to Minecraft to enable mod developers.'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('writeForgeVersionJson') {
|
||||
doLast {
|
||||
file('src/main/resources/forge_version.json').json = [
|
||||
forge: FORGE_VERSION,
|
||||
mc: MC_VERSION,
|
||||
mcp: MCP_VERSION
|
||||
]
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('jarJarOptionsJson', net.minecraftforge.forge.tasks.JarJarMetadataOptions) {
|
||||
// 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<String> getForgeVersion()
|
||||
abstract @Input Property<String> getMinecraftVersion()
|
||||
abstract @Input Property<String> 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
|
||||
|
||||
outputFile = file('src/main/resources/forge_version.json')
|
||||
}
|
||||
|
||||
tasks.register('jarJarOptionsJson', JarJarMetadataOptions) {
|
||||
metadataFile = project.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')
|
||||
@@ -118,29 +166,25 @@ tasks.register('jarJarOptionsJson', net.minecraftforge.forge.tasks.JarJarMetadat
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('generateResources').configure {
|
||||
dependsOn('eclipseJdt')
|
||||
dependsOn('eclipseJdtApt')
|
||||
dependsOn('eclipseFactorypath')
|
||||
dependsOn('writeForgeVersionJson')
|
||||
dependsOn('jarJarOptionsJson')
|
||||
tasks.named('generateResources') {
|
||||
dependsOn(
|
||||
tasks.named('eclipseJdt'),
|
||||
tasks.named('eclipseJdtApt'),
|
||||
tasks.named('eclipseFactorypath'),
|
||||
tasks.named('writeForgeVersionJson', WriteForgeVersionJson),
|
||||
tasks.named('jarJarOptionsJson')
|
||||
)
|
||||
}
|
||||
|
||||
tasks.named('sourcesJar') {
|
||||
dependsOn('jarJarOptionsJson')
|
||||
}
|
||||
|
||||
eclipse {
|
||||
classpath {
|
||||
// We need to set the default output directory for the log4j annotation processor
|
||||
// Ideally we'd just set the value, but the eclipse plugin deduplicates the output directories
|
||||
// So we have to do a hacky whenMerged
|
||||
//defaultOutputDir = file('bin/main')
|
||||
file.whenMerged {
|
||||
entries.each { entry ->
|
||||
if (entry.kind == 'output' && entry.hasProperty('path'))
|
||||
entry.path = 'bin/main'
|
||||
}
|
||||
}
|
||||
eclipse.classpath {
|
||||
// We need to set the default output directory for the log4j annotation processor
|
||||
// Ideally we'd just set the value, but the eclipse plugin deduplicates the output directories
|
||||
// So we have to do a hacky whenMerged
|
||||
//defaultOutputDir = file('bin/main')
|
||||
file.whenMerged {
|
||||
entries.each { entry ->
|
||||
if (entry.kind == 'output' && entry.hasProperty('path'))
|
||||
entry.path = 'bin/main'
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-4
@@ -6,11 +6,13 @@
|
||||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.electronwill.nightconfig.core.file.FileConfig;
|
||||
import com.electronwill.nightconfig.core.io.ParsingException;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.ModFileFactory;
|
||||
import net.minecraftforge.forgespi.locating.ModFileLoadingException;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -24,6 +26,7 @@ public class ModFileParser {
|
||||
return parser.build(modFile);
|
||||
}
|
||||
|
||||
// Note: Although @Nullable, several other places in FML assume ModFileInfo is not null. Keep this in mind
|
||||
public static @Nullable IModFileInfo modsTomlParser(final IModFile imodFile) {
|
||||
ModFile modFile = (ModFile) imodFile;
|
||||
LOGGER.debug(LogMarkers.LOADING,"Considering mod file candidate {}", modFile.getFilePath());
|
||||
@@ -34,9 +37,15 @@ public class ModFileParser {
|
||||
}
|
||||
|
||||
final FileConfig fileConfig = FileConfig.builder(modsjson).build();
|
||||
fileConfig.load();
|
||||
fileConfig.close();
|
||||
final NightConfigWrapper configWrapper = new NightConfigWrapper(fileConfig);
|
||||
return new ModFileInfo(modFile, configWrapper, configWrapper::setFile);
|
||||
try {
|
||||
fileConfig.load();
|
||||
fileConfig.close();
|
||||
final NightConfigWrapper configWrapper = new NightConfigWrapper(fileConfig);
|
||||
return new ModFileInfo(modFile, configWrapper, configWrapper::setFile);
|
||||
} catch (ParsingException e) {
|
||||
LOGGER.error("Mod candidate {} contains a corrupt or misconfigured toml.", modFile.getFileName());
|
||||
throw new ModFileLoadingException("Mod candidate " + modFile.getFileName() + " contains a corrupt or misconfigured toml.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -25,7 +25,9 @@ sealed abstract class ForgeProdLaunchHandler extends CommonLaunchHandler {
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
return List.of(getPathFromResource("net/minecraft/client/Minecraft.class"));
|
||||
// We use a marker because 3rd party launcher don't build their class paths correctly
|
||||
// https://github.com/MinecraftForge/MinecraftForge/issues/10797
|
||||
return List.of(getPathFromResource(".forge_patched_minecraft"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"artifact": "MixinExtras"
|
||||
},
|
||||
"version": {
|
||||
"range": "[0.5.3,)",
|
||||
"artifactVersion": "0.5.3"
|
||||
"range": "[0.5.4,)",
|
||||
"artifactVersion": "0.5.4"
|
||||
},
|
||||
"path": "",
|
||||
"isObfuscated": false
|
||||
@@ -24,7 +24,7 @@
|
||||
"artifact": "mixinextras-forge"
|
||||
},
|
||||
"version": {
|
||||
"artifactVersion": "0.5.3"
|
||||
"artifactVersion": "0.5.4"
|
||||
},
|
||||
"path": "",
|
||||
"isObfuscated": false
|
||||
|
||||
@@ -1,73 +1,78 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias(libs.plugins.apt)
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
|
||||
configurations.forEach{ it.transitive = false }
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
|
||||
implementation(libs.bundles.asm) // Needed by all the black magic
|
||||
implementation(libs.log4j.api)
|
||||
implementation(libs.gson)
|
||||
implementation(libs.modlauncher)
|
||||
implementation(libs.coremods.api)
|
||||
|
||||
testCompileOnly(libs.jetbrains.annotations)
|
||||
}
|
||||
gradleutils.displayName = 'Forge Transformers'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Forge-specific transformers unrelated to the FML project.'
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar) {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.forge.transformers',
|
||||
'Forge-Module-Layer': 'boot'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'Forge Transformers',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'Forge Transformers',
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': FORGE_VERSION
|
||||
] as LinkedHashMap, 'net/minecraftforge/forge/transformers/')
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications.register('mavenJava', MavenPublication) {
|
||||
from components.java
|
||||
artifactId = 'forge-transformers'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Forge-specific transformers unrelated to the FML project.'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
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/')
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,12 +42,6 @@
|
||||
"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;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/animal/frog/Tadpole",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/Strider",
|
||||
"methods": [
|
||||
@@ -85,24 +79,12 @@
|
||||
"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;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/zombie/ZombieVillager",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/npc/CatSpawner",
|
||||
"methods": [
|
||||
"spawnCat(Lnet/minecraft/core/BlockPos;Lnet/minecraft/server/level/ServerLevel;Z)V"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/npc/villager/Villager",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/raid/Raid",
|
||||
"methods": [
|
||||
@@ -158,11 +140,5 @@
|
||||
"methods": [
|
||||
"handleDataMarker(Ljava/lang/String;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/util/RandomSource;Lnet/minecraft/world/level/levelgen/structure/BoundingBox;)V"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
+23
-11
@@ -1,17 +1,29 @@
|
||||
# TODO Re-evaluate
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx6G
|
||||
org.gradle.daemon=false
|
||||
|
||||
org.gradle.warning.mode=all
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
JAVA_VERSION=25
|
||||
MC_VERSION=26.1
|
||||
MC_NEXT_VERSION=26.2
|
||||
MCP_VERSION=20260324.123823
|
||||
MAPPING_CHANNEL=official
|
||||
MAPPING_VERSION=26.1
|
||||
# TODO [ForgeDev] Enable this once ForgeDev 7 tasks are fully migrated
|
||||
org.gradle.configuration-cache=false
|
||||
org.gradle.configuration-cache.parallel=false
|
||||
#org.gradle.configuration-cache.problems=warn
|
||||
#org.gradle.configuration-cache.integrity-check=true
|
||||
|
||||
# Set to true before the first build of a new MC version, so we don't do compatibility checks
|
||||
CHECK_COMPATIBILITY=false
|
||||
# Set to true to allow for fuzzy patching. Useful during updateing
|
||||
UPDATING=false
|
||||
net.minecraftforge.gradleutils.ide.automatic.sources=true
|
||||
net.minecraftforge.gradleutils.compilation.defaults=true
|
||||
|
||||
net.minecraftforge.gradle.merge-source-sets=true
|
||||
|
||||
# Controls if the compatibility checks are auto-added to the 'check' task.
|
||||
# The check tasks are still created and can be run, they just are not grouped with the normal 'check' task.
|
||||
# Set to false for the first builds of a new Minecraft version.
|
||||
net.minecraftforge.forge.build.check.compatibility=false
|
||||
# Set to true to allow for fuzzy patching. Useful during updating.
|
||||
net.minecraftforge.forge.build.updating=false
|
||||
# Set to true to enable the 'validatePublish' task which is currently a work in progress
|
||||
net.minecraftforge.forgedev.validate.publish=false
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# 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.
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# 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/.
|
||||
@@ -84,7 +86,7 @@ done
|
||||
# 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 "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
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
|
||||
@@ -112,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -170,7 +171,6 @@ fi
|
||||
# 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" )
|
||||
|
||||
@@ -203,15 +203,14 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * 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" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+3
-2
@@ -13,6 +13,8 @@
|
||||
@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 ##########################################################################
|
||||
@@ -68,11 +70,10 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -1,66 +1,79 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
implementation(libs.unsafe)
|
||||
implementation(libs.securemodules)
|
||||
}
|
||||
gradleutils.displayName = 'JavaFMLMod'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Language provider for Minecraft Forge that provides basic Java mod functionality.'
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.javafmlmod',
|
||||
'FMLModType': 'LANGPROVIDER'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'JavaFMLMod',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'JavaFMLMod',
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': FORGE_VERSION
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/javafmlmod/')
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'javafmllanguage'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Language provider for Minecraft Forge that provides basic java mod functionality'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
implementation projects.fmlloader
|
||||
implementation projects.fmlcore
|
||||
implementation libs.unsafe
|
||||
implementation libs.securemodules
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar) {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.javafmlmod',
|
||||
'FMLModType' : 'LANGPROVIDER'
|
||||
])
|
||||
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/javafmlmod/')
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,77 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
gradleutils.displayName = 'LowCodeMod'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Language provider for Minecraft Forge that loads mods without a Java entrypoint.'
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.lowcodemod',
|
||||
'FMLModType': 'LANGPROVIDER'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'LowCodeMod',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1.0',
|
||||
'Implementation-Title': project.name,
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': FORGE_VERSION.split('\\.')[0]
|
||||
] as java.util.LinkedHashMap, 'net/minecraftforge/fml/lowcodemod/')
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'lowcodelanguage'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Language provider for Minecraft Forge that loads resource packs as mods'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
implementation projects.fmlloader
|
||||
implementation projects.fmlcore
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar) {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.lowcodemod',
|
||||
'FMLModType' : 'LANGPROVIDER'
|
||||
])
|
||||
attributes([
|
||||
'Specification-Title' : gradleutils.displayName.get(),
|
||||
'Specification-Vendor' : vendor,
|
||||
'Specification-Version' : '1.0',
|
||||
'Implementation-Title' : project.name,
|
||||
'Implementation-Vendor' : vendor,
|
||||
'Implementation-Version': forgeVersion.split('\\.')[0]
|
||||
], 'net/minecraftforge/fml/lowcodemod/')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
-45
@@ -1,64 +1,77 @@
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias libs.plugins.licenser
|
||||
alias libs.plugins.gradleutils
|
||||
alias libs.plugins.gitversion
|
||||
alias libs.plugins.changelog
|
||||
id 'net.minecraftforge.forge.build.convention'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.jetbrains.annotations)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
}
|
||||
gradleutils.displayName = 'MCLanguage'
|
||||
final vendor = 'Forge Development LLC'
|
||||
description = 'Language provider for Minecraft Forge that provides Minecraft Itself.'
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION)
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.mclanguageprovider',
|
||||
'FMLModType': 'LANGPROVIDER'
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'MCLanguage',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'MCLanguage',
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
'Implementation-Version': '1.0'
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/mclanguageprovider/')
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications.register('mavenJava', MavenPublication).configure {
|
||||
from components.java
|
||||
artifactId = 'mclanguage'
|
||||
pom {
|
||||
name = project.name
|
||||
description = 'Language provider for Minecraft Forge that provides Minecraft Itself'
|
||||
url = 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
changelog {
|
||||
from changelogBase
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly libs.jetbrains.annotations
|
||||
|
||||
implementation projects.fmlloader
|
||||
implementation projects.fmlcore
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
tasks.named('jar', Jar) {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.mclanguageprovider',
|
||||
'FMLModType' : 'LANGPROVIDER'
|
||||
])
|
||||
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/mclanguageprovider/')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -6,7 +6,7 @@ plugins {
|
||||
id 'java'
|
||||
id 'idea'
|
||||
id 'eclipse'
|
||||
id 'net.minecraftforge.gradle' version '[7.0.3,8)'
|
||||
id 'net.minecraftforge.gradle' version '[7.0.17,8)'
|
||||
}
|
||||
|
||||
version = '1.0.0'
|
||||
@@ -19,8 +19,6 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(25)
|
||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||
|
||||
minecraft {
|
||||
mappings channel: 'official', version: '@MC_VERSION@'
|
||||
|
||||
runs {
|
||||
configureEach {
|
||||
workingDir = layout.projectDirectory.dir('run')
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[versions]
|
||||
java = "25"
|
||||
minecraft = "26.1.2"
|
||||
minecraft-next = "26.2"
|
||||
mcp = "20260409.101008"
|
||||
changelog-base = "64.0"
|
||||
@@ -18,14 +18,14 @@
|
||||
@@ -103,6 +_,8 @@
|
||||
}
|
||||
|
||||
LOGGER.info("OpenGL debug message: {}", gldebug$logentry);
|
||||
LOGGER.info("OpenGL debug message: {}", entry);
|
||||
+ // TODO: [VEN] Trim the stack trace
|
||||
+ if (PRINT_STACKTRACE_ON_ERROR) LOGGER.info("Trace: ", new Throwable("GlDebug"));
|
||||
}
|
||||
|
||||
public List<String> getLastOpenGlDebugMessages() {
|
||||
@@ -126,7 +_,7 @@
|
||||
GlDebug gldebug1 = new GlDebug();
|
||||
GlDebug debug = new GlDebug();
|
||||
enabledExtensions.add("GL_KHR_debug");
|
||||
GL11.glEnable(37600);
|
||||
- if (debugSynchronousGlLogs) {
|
||||
@@ -34,8 +34,8 @@
|
||||
}
|
||||
|
||||
@@ -140,7 +_,7 @@
|
||||
} else if (glcapabilities.GL_ARB_debug_output && GlDevice.USE_GL_ARB_debug_output) {
|
||||
GlDebug gldebug = new GlDebug();
|
||||
} else if (caps.GL_ARB_debug_output && GlDevice.USE_GL_ARB_debug_output) {
|
||||
GlDebug debug = new GlDebug();
|
||||
enabledExtensions.add("GL_ARB_debug_output");
|
||||
- if (debugSynchronousGlLogs) {
|
||||
+ if (debugSynchronousGlLogs | PRINT_STACKTRACE_ON_ERROR) {
|
||||
|
||||
@@ -24,31 +24,39 @@
|
||||
+ @Override
|
||||
+ public GpuTexture createTexture(@Nullable String label, @GpuTexture.Usage final int usage, final TextureFormat format, final int width, final int height, final int depthOrLayers, final int mipLevels, boolean stencil) {
|
||||
GlStateManager.clearGlErrors();
|
||||
int i = GlStateManager._genTexture();
|
||||
int id = GlStateManager._genTexture();
|
||||
if (label == null) {
|
||||
@@ -169,14 +_,14 @@
|
||||
for (int k : GlConst.CUBEMAP_TARGETS) {
|
||||
for (int l = 0; l < mipLevels; l++) {
|
||||
@@ -171,12 +_,12 @@
|
||||
GlStateManager._texImage2D(
|
||||
- k, l, GlConst.toGlInternalId(format), width >> l, height >> l, 0, GlConst.toGlExternalId(format), GlConst.toGlType(format), null
|
||||
+ k, l, GlConst.toGlInternalId(format, stencil), width >> l, height >> l, 0, GlConst.toGlExternalId(format, stencil), GlConst.toGlType(format, stencil), null
|
||||
cubeTarget,
|
||||
i,
|
||||
- GlConst.toGlInternalId(format),
|
||||
+ GlConst.toGlInternalId(format, stencil),
|
||||
width >> i,
|
||||
height >> i,
|
||||
0,
|
||||
- GlConst.toGlExternalId(format),
|
||||
- GlConst.toGlType(format),
|
||||
+ GlConst.toGlExternalId(format, stencil),
|
||||
+ GlConst.toGlType(format, stencil),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -184,7 +_,7 @@
|
||||
} else {
|
||||
for (int i1 = 0; i1 < mipLevels; i1++) {
|
||||
for (int i = 0; i < mipLevels; i++) {
|
||||
GlStateManager._texImage2D(
|
||||
- j, i1, GlConst.toGlInternalId(format), width >> i1, height >> i1, 0, GlConst.toGlExternalId(format), GlConst.toGlType(format), null
|
||||
+ j, i1, GlConst.toGlInternalId(format, stencil), width >> i1, height >> i1, 0, GlConst.toGlExternalId(format, stencil), GlConst.toGlType(format, stencil), null
|
||||
- target, i, GlConst.toGlInternalId(format), width >> i, height >> i, 0, GlConst.toGlExternalId(format), GlConst.toGlType(format), null
|
||||
+ target, i, GlConst.toGlInternalId(format, stencil), width >> i, height >> i, 0, GlConst.toGlExternalId(format, stencil), GlConst.toGlType(format, stencil), null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -187,7 +_,7 @@
|
||||
} else if (j1 != 0) {
|
||||
throw new IllegalStateException("OpenGL error " + j1);
|
||||
@@ -195,7 +_,7 @@
|
||||
} else if (error != 0) {
|
||||
throw new IllegalStateException("OpenGL error " + error);
|
||||
} else {
|
||||
- GlTexture gltexture = new GlTexture(usage, label, format, width, height, depthOrLayers, mipLevels, i);
|
||||
+ GlTexture gltexture = new GlTexture(usage, label, format, width, height, depthOrLayers, mipLevels, i, stencil);
|
||||
this.debugLabels.applyLabel(gltexture);
|
||||
return gltexture;
|
||||
- GlTexture texture = new GlTexture(usage, label, format, width, height, depthOrLayers, mipLevels, id);
|
||||
+ GlTexture texture = new GlTexture(usage, label, format, width, height, depthOrLayers, mipLevels, id, stencil);
|
||||
this.debugLabels.applyLabel(texture);
|
||||
return texture;
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
if (this.useDepth) {
|
||||
- this.depthTexture = gpudevice.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, width, height, 1, 1);
|
||||
+ this.depthTexture = gpudevice.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, width, height, 1, 1, this.stencilEnabled);
|
||||
this.depthTextureView = gpudevice.createTextureView(this.depthTexture);
|
||||
- this.depthTexture = device.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, width, height, 1, 1);
|
||||
+ this.depthTexture = device.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, width, height, 1, 1, this.stencilEnabled);
|
||||
this.depthTextureView = device.createTextureView(this.depthTexture);
|
||||
}
|
||||
|
||||
@@ -124,5 +_,26 @@
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
--- a/com/mojang/blaze3d/platform/Window.java
|
||||
+++ b/com/mojang/blaze3d/platform/Window.java
|
||||
@@ -97,8 +_,9 @@
|
||||
Monitor monitor = this.screenManager.getMonitor(GLFW.glfwGetPrimaryMonitor());
|
||||
Monitor initialMonitor = this.screenManager.getMonitor(GLFW.glfwGetPrimaryMonitor());
|
||||
this.windowedWidth = this.width = allowedWindowMinSize(displayData.width());
|
||||
this.windowedHeight = this.height = allowedWindowMinSize(displayData.height());
|
||||
- this.handle = this.createWindow(backend, this.width, this.height, title, this.fullscreen && monitor != null ? monitor.getMonitor() : 0L);
|
||||
+ this.handle = net.minecraftforge.fml.loading.ImmediateWindowHandler.setupMinecraftWindow(this.width, this.height, title, this.fullscreen && monitor != null ? monitor.getMonitor() : 0L, () -> backend);
|
||||
- this.handle = this.createWindow(backend, this.width, this.height, title, this.fullscreen && initialMonitor != null ? initialMonitor.getMonitor() : 0L);
|
||||
+ this.handle = net.minecraftforge.fml.loading.ImmediateWindowHandler.setupMinecraftWindow(this.width, this.height, title, this.fullscreen && initialMonitor != null ? initialMonitor.getMonitor() : 0L, () -> backend);
|
||||
this.backend = backend;
|
||||
+ if (!net.minecraftforge.fml.loading.ImmediateWindowHandler.positionWindow(Optional.ofNullable(monitor), w->this.width = this.windowedWidth = w, h->this.height = this.windowedHeight = h, x->this.x = this.windowedX = x, y->this.y = this.windowedY = y)) {
|
||||
if (monitor != null) {
|
||||
VideoMode videomode = monitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
|
||||
this.windowedX = this.x = monitor.getX() + videomode.getWidth() / 2 - this.width / 2;
|
||||
+ if (!net.minecraftforge.fml.loading.ImmediateWindowHandler.positionWindow(Optional.ofNullable(initialMonitor), w->this.width = this.windowedWidth = w, h->this.height = this.windowedHeight = h, x->this.x = this.windowedX = x, y->this.y = this.windowedY = y)) {
|
||||
if (initialMonitor != null) {
|
||||
VideoMode mode = initialMonitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
|
||||
this.windowedX = this.x = initialMonitor.getX() + mode.getWidth() / 2 - this.width / 2;
|
||||
@@ -110,6 +_,7 @@
|
||||
this.windowedX = this.x = aint1[0];
|
||||
this.windowedY = this.y = aint[0];
|
||||
this.windowedX = this.x = actualX[0];
|
||||
this.windowedY = this.y = actualY[0];
|
||||
}
|
||||
+ }
|
||||
|
||||
this.setMode();
|
||||
this.refreshFramebufferSize();
|
||||
@@ -300,6 +_,9 @@
|
||||
GLFW.glfwGetFramebufferSize(this.handle, aint, aint1);
|
||||
this.framebufferWidth = aint[0] > 0 ? aint[0] : 1;
|
||||
this.framebufferHeight = aint1[0] > 0 ? aint1[0] : 1;
|
||||
GLFW.glfwGetFramebufferSize(this.handle, outWidth, outHeight);
|
||||
this.framebufferWidth = outWidth[0] > 0 ? outWidth[0] : 1;
|
||||
this.framebufferHeight = outHeight[0] > 0 ? outHeight[0] : 1;
|
||||
+ if (this.framebufferHeight == 0 || this.framebufferWidth == 0) {
|
||||
+ net.minecraftforge.fml.loading.ImmediateWindowHandler.updateFBSize(w -> this.framebufferWidth = w, h -> this.framebufferHeight = h);
|
||||
+ }
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
private VertexFormat(final List<VertexFormatElement> elements, final List<String> names, final IntList offsets, final int vertexSize) {
|
||||
this.elements = elements;
|
||||
@@ -41,6 +_,11 @@
|
||||
int j = vertexformatelement != null ? elements.indexOf(vertexformatelement) : -1;
|
||||
this.offsetsByElement[i] = j != -1 ? offsets.getInt(j) : -1;
|
||||
int index = element != null ? elements.indexOf(element) : -1;
|
||||
this.offsetsByElement[id] = index != -1 ? offsets.getInt(index) : -1;
|
||||
}
|
||||
+
|
||||
+ ImmutableMap.Builder<String, VertexFormatElement> elementMapping = ImmutableMap.builder();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/math/Transformation.java
|
||||
+++ b/com/mojang/math/Transformation.java
|
||||
@@ -17,7 +_,7 @@
|
||||
@@ -16,7 +_,7 @@
|
||||
import org.joml.Vector3fc;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
private static final Vector3fc ZERO_TRANSLATION = new Vector3f();
|
||||
private static final Vector3fc UNIT_SCALE = new Vector3f(1.0F, 1.0F, 1.0F);
|
||||
private static final Quaternionfc ZERO_ROTATION = new Quaternionf();
|
||||
@@ -172,6 +_,20 @@
|
||||
@@ -171,6 +_,20 @@
|
||||
this.scale().lerp(that.scale(), progress, new Vector3f()),
|
||||
this.rightRotation().slerp(that.rightRotation(), progress, new Quaternionf())
|
||||
);
|
||||
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
--- a/com/mojang/realmsclient/gui/screens/RealmsResetWorldScreen.java
|
||||
+++ b/com/mojang/realmsclient/gui/screens/RealmsResetWorldScreen.java
|
||||
@@ -303,7 +_,7 @@
|
||||
int k = this.getY();
|
||||
graphics.blit(RenderPipelines.GUI_TEXTURED, this.image, j + 2, k + 2, 0.0F, 0.0F, 56, 56, 56, 56, 56, 56, i);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SLOT_FRAME_SPRITE, j, k, 60, 60, i);
|
||||
- int l = flag ? -6250336 : -1;
|
||||
+ int l = getFGColor();
|
||||
graphics.centeredText(RealmsResetWorldScreen.this.font, this.getMessage(), j + 28, k - 14, l);
|
||||
@@ -302,7 +_,7 @@
|
||||
int y = this.getY();
|
||||
graphics.blit(RenderPipelines.GUI_TEXTURED, this.image, x + 2, y + 2, 0.0F, 0.0F, 56, 56, 56, 56, 56, 56, color);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SLOT_FRAME_SPRITE, x, y, 60, 60, color);
|
||||
- int textColor = hoveredOrFocused ? -6250336 : -1;
|
||||
+ int textColor = getFGColor();
|
||||
graphics.centeredText(RealmsResetWorldScreen.this.font, this.getMessage(), x + 28, y - 14, textColor);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
builder.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
|
||||
- builder.append("Stacktrace:\n");
|
||||
-
|
||||
- for (StackTraceElement stacktraceelement : this.uncategorizedStackTrace) {
|
||||
- builder.append("\t").append("at ").append(stacktraceelement);
|
||||
- for (StackTraceElement element : this.uncategorizedStackTrace) {
|
||||
- builder.append("\t").append("at ").append(element);
|
||||
- builder.append("\n");
|
||||
- }
|
||||
-
|
||||
@@ -17,7 +17,7 @@
|
||||
+ builder.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.uncategorizedStackTrace));
|
||||
}
|
||||
|
||||
for (CrashReportCategory crashreportcategory : this.details) {
|
||||
for (CrashReportCategory entry : this.details) {
|
||||
@@ -73,6 +_,7 @@
|
||||
builder.append("\n\n");
|
||||
}
|
||||
@@ -27,22 +27,22 @@
|
||||
}
|
||||
|
||||
@@ -92,18 +_,7 @@
|
||||
throwable.setStackTrace(this.exception.getStackTrace());
|
||||
exception.setStackTrace(this.exception.getStackTrace());
|
||||
}
|
||||
|
||||
- String s;
|
||||
- String var4;
|
||||
- try {
|
||||
- stringwriter = new StringWriter();
|
||||
- printwriter = new PrintWriter(stringwriter);
|
||||
- throwable.printStackTrace(printwriter);
|
||||
- s = stringwriter.toString();
|
||||
- writer = new StringWriter();
|
||||
- printWriter = new PrintWriter(writer);
|
||||
- exception.printStackTrace(printWriter);
|
||||
- var4 = writer.toString();
|
||||
- } finally {
|
||||
- IOUtils.closeQuietly((Writer)stringwriter);
|
||||
- IOUtils.closeQuietly((Writer)printwriter);
|
||||
- IOUtils.closeQuietly((Writer)writer);
|
||||
- IOUtils.closeQuietly((Writer)printWriter);
|
||||
- }
|
||||
-
|
||||
- return s;
|
||||
+ return net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(throwable);
|
||||
- return var4;
|
||||
+ return net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(exception);
|
||||
}
|
||||
|
||||
public String getFriendlyReport(final ReportType reportType, final List<String> extraComments) {
|
||||
@@ -1,26 +1,26 @@
|
||||
--- a/net/minecraft/CrashReportCategory.java
|
||||
+++ b/net/minecraft/CrashReportCategory.java
|
||||
@@ -114,8 +_,10 @@
|
||||
if (astacktraceelement.length <= 0) {
|
||||
@@ -140,8 +_,10 @@
|
||||
if (full.length <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
- this.stackTrace = new StackTraceElement[astacktraceelement.length - 3 - nestedOffset];
|
||||
- System.arraycopy(astacktraceelement, 3 + nestedOffset, this.stackTrace, 0, this.stackTrace.length);
|
||||
+ int len = astacktraceelement.length - 3 - nestedOffset;
|
||||
+ if (len <= 0) len = astacktraceelement.length;
|
||||
- this.stackTrace = new StackTraceElement[full.length - 3 - nestedOffset];
|
||||
- System.arraycopy(full, 3 + nestedOffset, this.stackTrace, 0, this.stackTrace.length);
|
||||
+ int len = full.length - 3 - nestedOffset;
|
||||
+ if (len <= 0) len = full.length;
|
||||
+ this.stackTrace = new StackTraceElement[len];
|
||||
+ System.arraycopy(astacktraceelement, astacktraceelement.length - len, this.stackTrace, 0, this.stackTrace.length);
|
||||
+ System.arraycopy(full, full.length - len, this.stackTrace, 0, this.stackTrace.length);
|
||||
return this.stackTrace.length;
|
||||
}
|
||||
}
|
||||
@@ -162,16 +_,16 @@
|
||||
@@ -188,16 +_,16 @@
|
||||
|
||||
if (this.stackTrace != null && this.stackTrace.length > 0) {
|
||||
builder.append("\nStacktrace:");
|
||||
-
|
||||
- for (StackTraceElement stacktraceelement : this.stackTrace) {
|
||||
- for (StackTraceElement element : this.stackTrace) {
|
||||
- builder.append("\n\tat ");
|
||||
- builder.append(stacktraceelement);
|
||||
- builder.append(element);
|
||||
- }
|
||||
+ builder.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.stackTrace));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/net/minecraft/advancements/Advancement.java
|
||||
+++ b/net/minecraft/advancements/Advancement.java
|
||||
@@ -227,7 +_,11 @@
|
||||
@@ -219,7 +_,11 @@
|
||||
}
|
||||
|
||||
public AdvancementHolder save(final Consumer<AdvancementHolder> output, final String name) {
|
||||
- AdvancementHolder advancementholder = this.build(Identifier.parse(name));
|
||||
- AdvancementHolder advancement = this.build(Identifier.parse(name));
|
||||
+ return save(output, Identifier.parse(name));
|
||||
+ }
|
||||
+
|
||||
+ public AdvancementHolder save(Consumer<AdvancementHolder> output, Identifier id) {
|
||||
+ AdvancementHolder advancementholder = this.build(id);
|
||||
output.accept(advancementholder);
|
||||
return advancementholder;
|
||||
+ AdvancementHolder advancement = this.build(id);
|
||||
output.accept(advancement);
|
||||
return advancement;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
--- a/net/minecraft/advancements/AdvancementRewards.java
|
||||
+++ b/net/minecraft/advancements/AdvancementRewards.java
|
||||
@@ -44,6 +_,7 @@
|
||||
LootParams lootparams = new LootParams.Builder(serverlevel)
|
||||
@@ -43,6 +_,7 @@
|
||||
LootParams params = new LootParams.Builder(level)
|
||||
.withParameter(LootContextParams.THIS_ENTITY, player)
|
||||
.withParameter(LootContextParams.ORIGIN, player.position())
|
||||
+ .withLuck(player.getLuck())
|
||||
.create(LootContextParamSets.ADVANCEMENT_REWARD);
|
||||
boolean flag = false;
|
||||
boolean changes = false;
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
@@ -217,12 +_,14 @@
|
||||
return 90.0F;
|
||||
} else {
|
||||
float f = this.minecraft.options.fov().get().intValue() * Mth.lerp(partialTicks, this.oldFovModifier, this.fovModifier);
|
||||
- return this.modifyFovBasedOnDeathOrFluid(partialTicks, f);
|
||||
+ var ret = this.modifyFovBasedOnDeathOrFluid(partialTicks, f);
|
||||
float fov = this.minecraft.options.fov().get().intValue() * Mth.lerp(partialTicks, this.oldFovModifier, this.fovModifier);
|
||||
- return this.modifyFovBasedOnDeathOrFluid(partialTicks, fov);
|
||||
+ var ret = this.modifyFovBasedOnDeathOrFluid(partialTicks, fov);
|
||||
+ return net.minecraftforge.client.event.ForgeEventFactoryClient.fireComputeFov(this.minecraft.gameRenderer, this, partialTicks, ret, true).getFOV();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
|
||||
private static void forAllKeyMappings(final InputConstants.Key key, final Consumer<KeyMapping> operation) {
|
||||
- List<KeyMapping> list = MAP.get(key);
|
||||
+ List<KeyMapping> list = MAP.getAll(key);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
for (KeyMapping keymapping : list) {
|
||||
operation.accept(keymapping);
|
||||
- List<KeyMapping> keyMappings = MAP.get(key);
|
||||
+ List<KeyMapping> keyMappings = MAP.getAll(key);
|
||||
if (keyMappings != null && !keyMappings.isEmpty()) {
|
||||
for (KeyMapping keyMapping : keyMappings) {
|
||||
operation.accept(keyMapping);
|
||||
@@ -106,7 +_,7 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/KeyboardHandler.java
|
||||
+++ b/net/minecraft/client/KeyboardHandler.java
|
||||
@@ -516,7 +_,7 @@
|
||||
@@ -514,7 +_,7 @@
|
||||
if (screen != null) {
|
||||
try {
|
||||
if (action != 1 && action != 2) {
|
||||
@@ -9,16 +9,16 @@
|
||||
if (options.keyDebugModifier.matches(event)) {
|
||||
this.usedDebugKeyAsModifier = false;
|
||||
}
|
||||
@@ -525,7 +_,7 @@
|
||||
@@ -523,7 +_,7 @@
|
||||
}
|
||||
} else {
|
||||
screen.afterKeyboardAction();
|
||||
- if (screen.keyPressed(event)) {
|
||||
+ if (net.minecraftforge.client.ForgeHooksClient.onScreenKeyPressed(screen, event)) {
|
||||
if (this.minecraft.screen == null) {
|
||||
InputConstants.Key inputconstants$key = InputConstants.getKey(event);
|
||||
KeyMapping.set(inputconstants$key, false);
|
||||
@@ -597,6 +_,7 @@
|
||||
InputConstants.Key key = InputConstants.getKey(event);
|
||||
KeyMapping.set(key, false);
|
||||
@@ -595,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,7 +_,7 @@
|
||||
@@ -603,7 +_,7 @@
|
||||
Screen screen = this.minecraft.screen;
|
||||
if (screen != null && this.minecraft.getOverlay() == null) {
|
||||
try {
|
||||
- screen.charTyped(event);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(screen, event);
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "charTyped event handler");
|
||||
screen.fillCrashDetails(crashreport);
|
||||
} catch (Throwable var8) {
|
||||
CrashReport report = CrashReport.forThrowable(var8, "charTyped event handler");
|
||||
screen.fillCrashDetails(report);
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Minecraft.java
|
||||
+++ b/net/minecraft/client/Minecraft.java
|
||||
@@ -272,7 +_,7 @@
|
||||
@@ -268,7 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,7 +9,7 @@
|
||||
private static Minecraft instance;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int MAX_TICKS_PER_UPDATE = 10;
|
||||
@@ -436,7 +_,6 @@
|
||||
@@ -432,7 +_,6 @@
|
||||
}
|
||||
}, Util.nonCriticalIoPool());
|
||||
LOGGER.info("Setting user: {}", this.user.getName());
|
||||
@@ -17,8 +17,8 @@
|
||||
this.demo = gameConfig.game.demo;
|
||||
this.allowsMultiplayer = !gameConfig.game.disableMultiplayer;
|
||||
this.allowsChat = !gameConfig.game.disableChat;
|
||||
@@ -522,14 +_,14 @@
|
||||
LOGGER.error("Couldn't set icon", (Throwable)ioexception);
|
||||
@@ -518,14 +_,14 @@
|
||||
LOGGER.error("Couldn't set icon", (Throwable)var23);
|
||||
}
|
||||
|
||||
+ // FORGE: Move mouse and keyboard handler setup further below
|
||||
@@ -34,7 +34,7 @@
|
||||
this.resourcePackRepository.reload();
|
||||
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
|
||||
this.languageManager = new LanguageManager(this.options.languageCode, languageData -> {
|
||||
@@ -617,6 +_,7 @@
|
||||
@@ -613,6 +_,7 @@
|
||||
this.particleResources = new ParticleResources();
|
||||
this.resourceManager.registerReloadListener(this.particleResources);
|
||||
this.particleEngine = new ParticleEngine(this.level, this.particleResources);
|
||||
@@ -42,17 +42,17 @@
|
||||
this.particleResources.onReload(this.particleEngine::clearParticles);
|
||||
this.waypointStyles = new WaypointStyleManager();
|
||||
this.resourceManager.registerReloadListener(this.waypointStyles);
|
||||
@@ -638,6 +_,9 @@
|
||||
@@ -634,6 +_,9 @@
|
||||
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
|
||||
this.resourceManager.registerReloadListener(this.regionalCompliancies);
|
||||
this.gui = new Gui(this);
|
||||
+ // FORGE: Moved keyboard and mouse handler setup below ingame gui creation to prevent NPEs in them.
|
||||
+ this.mouseHandler.setup(this.window);
|
||||
+ this.keyboardHandler.setup(this.window);
|
||||
RealmsClient realmsclient = RealmsClient.getOrCreate(this);
|
||||
this.realmsDataFetcher = new RealmsDataFetcher(realmsclient);
|
||||
RealmsClient realmsClient = RealmsClient.getOrCreate(this);
|
||||
this.realmsDataFetcher = new RealmsDataFetcher(realmsClient);
|
||||
RenderSystem.setErrorCallback(this::onFullscreenError);
|
||||
@@ -669,6 +_,7 @@
|
||||
@@ -665,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,34 +60,33 @@
|
||||
this.window.updateVsync(this.options.enableVsync().get());
|
||||
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
|
||||
this.window.setAllowCursorChanges(this.options.allowCursorChanges().get());
|
||||
@@ -695,14 +_,16 @@
|
||||
@@ -690,14 +_,15 @@
|
||||
.createReload(Util.backgroundExecutor().forName("resourceLoad"), this, RESOURCE_RELOAD_INITIAL_TASK, packs);
|
||||
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
|
||||
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, gameConfig.quickPlay);
|
||||
this.setOverlay(
|
||||
- new LoadingOverlay(this, reloadinstance, maybeT -> Util.ifElse(maybeT, t -> this.rollbackResourcePacks(t, minecraft$gameloadcookie), () -> {
|
||||
+ net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(
|
||||
+ () -> this, () -> reloadinstance, maybeT -> Util.ifElse(maybeT, t -> this.rollbackResourcePacks(t, minecraft$gameloadcookie), () -> {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
this.selfTest();
|
||||
}
|
||||
Minecraft.GameLoadCookie loadCookie = new Minecraft.GameLoadCookie(realmsClient, gameConfig.quickPlay);
|
||||
- this.setOverlay(new LoadingOverlay(this, reloadInstance, maybeT -> Util.ifElse(maybeT, t -> this.rollbackResourcePacks(t, loadCookie), () -> {
|
||||
+ this.setOverlay(net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(() -> this, () ->reloadInstance, maybeT -> Util.ifElse(maybeT, t -> this.rollbackResourcePacks(t, loadCookie), () -> {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
this.selfTest();
|
||||
}
|
||||
|
||||
this.reloadStateTracker.finishReload();
|
||||
this.onResourceLoadFinished(minecraft$gameloadcookie);
|
||||
- }), false)
|
||||
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
|
||||
+ }), false).get()
|
||||
);
|
||||
this.reloadStateTracker.finishReload();
|
||||
this.onResourceLoadFinished(loadCookie);
|
||||
- }), false));
|
||||
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
|
||||
+ }), false).get());
|
||||
this.quickPlayLog = QuickPlayLog.of(gameConfig.quickPlay.logPath());
|
||||
this.framerateLimitTracker = new FramerateLimitTracker(this.options, this);
|
||||
@@ -822,6 +_,7 @@
|
||||
StringBuilder stringbuilder = new StringBuilder("Minecraft");
|
||||
this.fpsPieProfiler = new ContinuousProfiler(Util.timeSource, () -> this.fpsPieRenderTicks, this.framerateLimitTracker::isHeavilyThrottled);
|
||||
@@ -816,6 +_,7 @@
|
||||
StringBuilder builder = new StringBuilder("Minecraft");
|
||||
if (checkModStatus().shouldReportAsModified()) {
|
||||
stringbuilder.append("*");
|
||||
+ stringbuilder.append(" Forge");
|
||||
builder.append("*");
|
||||
+ builder.append(" Forge");
|
||||
}
|
||||
|
||||
stringbuilder.append(" ");
|
||||
@@ -845,6 +_,8 @@
|
||||
builder.append(" ");
|
||||
@@ -839,6 +_,8 @@
|
||||
}
|
||||
|
||||
private UserApiService createUserApiService(final YggdrasilAuthenticationService authService, final GameConfig config) {
|
||||
@@ -96,7 +95,7 @@
|
||||
return config.game.offlineDeveloperMode ? UserApiService.OFFLINE : authService.createUserApiService(config.user.user.getAccessToken());
|
||||
}
|
||||
|
||||
@@ -857,7 +_,7 @@
|
||||
@@ -851,7 +_,7 @@
|
||||
}
|
||||
|
||||
private void rollbackResourcePacks(final Throwable t, final Minecraft.@Nullable GameLoadCookie loadCookie) {
|
||||
@@ -105,7 +104,7 @@
|
||||
this.clearResourcePacksOnError(t, null, loadCookie);
|
||||
} else {
|
||||
Util.throwAsRuntime(t);
|
||||
@@ -1134,12 +_,6 @@
|
||||
@@ -1128,12 +_,6 @@
|
||||
LOGGER.error("setScreen called from non-game thread");
|
||||
}
|
||||
|
||||
@@ -118,7 +117,7 @@
|
||||
if (screen == null) {
|
||||
if (this.clientLevelTeardownInProgress) {
|
||||
throw new IllegalStateException("Trying to return to in-game GUI during disconnection");
|
||||
@@ -1158,6 +_,23 @@
|
||||
@@ -1152,6 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,33 +141,33 @@
|
||||
this.screen = screen;
|
||||
if (this.screen != null) {
|
||||
this.screen.added();
|
||||
@@ -1241,6 +_,7 @@
|
||||
@@ -1235,6 +_,7 @@
|
||||
Util.shutdownExecutors();
|
||||
RenderSystem.getSamplerCache().close();
|
||||
RenderSystem.getDevice().close();
|
||||
+ net.minecraftforge.fml.config.ConfigTracker.forceUnload();
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Shutdown failure!", throwable);
|
||||
throw throwable;
|
||||
@@ -1352,7 +_,9 @@
|
||||
profilerfiller.popPush("gpuAsync");
|
||||
} catch (Throwable var5) {
|
||||
LOGGER.error("Shutdown failure!", var5);
|
||||
throw var5;
|
||||
@@ -1346,7 +_,9 @@
|
||||
profiler.popPush("gpuAsync");
|
||||
RenderSystem.executePendingTasks();
|
||||
profilerfiller.pop();
|
||||
profiler.pop();
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickStart(this.deltaTracker);
|
||||
this.gameRenderer.render(this.deltaTracker, advanceGameTime);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickEnd(this.deltaTracker);
|
||||
profilerfiller.push("present");
|
||||
profiler.push("present");
|
||||
if (!this.gameRenderer.getGameRenderState().windowRenderState.isMinimized) {
|
||||
this.mainRenderTarget.blitToScreen();
|
||||
@@ -1456,6 +_,7 @@
|
||||
this.window.setGuiScale(i);
|
||||
@@ -1450,6 +_,7 @@
|
||||
this.window.setGuiScale(guiScale);
|
||||
if (this.screen != null) {
|
||||
this.screen.resize(this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
+ net.minecraftforge.client.ForgeHooksClient.resizeGuiLayers(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
}
|
||||
|
||||
this.mouseHandler.setIgnoreFirstMove();
|
||||
@@ -1600,6 +_,7 @@
|
||||
@@ -1601,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -176,29 +175,29 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@@ -1629,10 +_,18 @@
|
||||
@@ -1630,10 +_,18 @@
|
||||
if (down && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
BlockHitResult blockHit = (BlockHitResult)this.hitResult;
|
||||
BlockPos pos = blockHit.getBlockPos();
|
||||
- if (!this.level.getBlockState(pos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(pos)) {
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
|
||||
+ if (net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent)) {
|
||||
+ if (inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
+ this.level.addBreakingBlockEffect(pos, blockHit);
|
||||
+ this.player.swing(InteractionHand.MAIN_HAND);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
Direction direction = blockhitresult.getDirection();
|
||||
- if (this.gameMode.continueDestroyBlock(blockpos, direction)) {
|
||||
- this.level.addBreakingBlockEffect(blockpos, direction);
|
||||
+ if (this.gameMode.continueDestroyBlock(blockpos, direction) && inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
Direction direction = blockHit.getDirection();
|
||||
- if (this.gameMode.continueDestroyBlock(pos, direction)) {
|
||||
- this.level.addBreakingBlockEffect(pos, direction);
|
||||
+ if (this.gameMode.continueDestroyBlock(pos, direction) && inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(pos, blockHit);
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1675,6 +_,8 @@
|
||||
@@ -1676,6 +_,8 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return true;
|
||||
} else {
|
||||
@@ -206,17 +205,17 @@
|
||||
+ if (!net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent))
|
||||
switch (this.hitResult.getType()) {
|
||||
case ENTITY:
|
||||
AttackRange attackrange = itemstack.get(DataComponents.ATTACK_RANGE);
|
||||
@@ -1685,7 +_,7 @@
|
||||
AttackRange customItemRange = heldItem.get(DataComponents.ATTACK_RANGE);
|
||||
@@ -1686,7 +_,7 @@
|
||||
case BLOCK:
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
|
||||
if (this.level.getBlockState(blockpos).isAir()) {
|
||||
flag = true;
|
||||
@@ -1698,8 +_,10 @@
|
||||
BlockHitResult blockHit = (BlockHitResult)this.hitResult;
|
||||
BlockPos pos = blockHit.getBlockPos();
|
||||
- if (!this.level.getBlockState(pos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(pos)) {
|
||||
this.gameMode.startDestroyBlock(pos, blockHit.getDirection());
|
||||
if (this.level.getBlockState(pos).isAir()) {
|
||||
endAttack = true;
|
||||
@@ -1699,8 +_,10 @@
|
||||
}
|
||||
|
||||
this.player.resetAttackStrengthTicker();
|
||||
@@ -225,83 +224,83 @@
|
||||
|
||||
+ if (inputEvent.shouldSwingHand())
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return flag;
|
||||
return endAttack;
|
||||
}
|
||||
@@ -1716,6 +_,12 @@
|
||||
@@ -1717,6 +_,12 @@
|
||||
}
|
||||
|
||||
for (InteractionHand interactionhand : InteractionHand.values()) {
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(1, this.options.keyUse, interactionhand);
|
||||
for (InteractionHand hand : InteractionHand.values()) {
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(1, this.options.keyUse, hand);
|
||||
+ if (net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent)) {
|
||||
+ if (inputEvent.shouldSwingHand()) this.player.swing(interactionhand);
|
||||
+ if (inputEvent.shouldSwingHand()) this.player.swing(hand);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
ItemStack itemstack = this.player.getItemInHand(interactionhand);
|
||||
if (!itemstack.isItemEnabled(this.level.enabledFeatures())) {
|
||||
ItemStack heldItem = this.player.getItemInHand(hand);
|
||||
if (!heldItem.isItemEnabled(this.level.enabledFeatures())) {
|
||||
return;
|
||||
@@ -1734,7 +_,7 @@
|
||||
&& this.gameMode.interact(this.player, entity, entityhitresult, interactionhand) instanceof InteractionResult.Success interactionresult$success2
|
||||
)
|
||||
{
|
||||
- if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
@@ -1733,7 +_,7 @@
|
||||
|
||||
if (this.player.isWithinEntityInteractionRange(entity, 0.0)
|
||||
&& this.gameMode.interact(this.player, entity, entityHit, hand) instanceof InteractionResult.Success success) {
|
||||
- if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(hand);
|
||||
}
|
||||
|
||||
@@ -1746,7 +_,7 @@
|
||||
int i = itemstack.getCount();
|
||||
InteractionResult interactionresult = this.gameMode.useItemOn(this.player, interactionhand, blockhitresult);
|
||||
if (interactionresult instanceof InteractionResult.Success interactionresult$success) {
|
||||
- if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.player.hasInfiniteMaterials())) {
|
||||
this.gameRenderer.itemInHandRenderer.itemUsed(interactionhand);
|
||||
@@ -1762,6 +_,9 @@
|
||||
@@ -1745,7 +_,7 @@
|
||||
int oldCount = heldItem.getCount();
|
||||
InteractionResult useResult = this.gameMode.useItemOn(this.player, hand, blockHit);
|
||||
if (useResult instanceof InteractionResult.Success success) {
|
||||
- if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(hand);
|
||||
if (!heldItem.isEmpty() && (heldItem.getCount() != oldCount || this.player.hasInfiniteMaterials())) {
|
||||
this.gameRenderer.itemInHandRenderer.itemUsed(hand);
|
||||
@@ -1761,6 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (itemstack.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS))
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onRightClickEmpty(this.player, interactionhand);
|
||||
+ if (heldItem.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS))
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onRightClickEmpty(this.player, hand);
|
||||
+
|
||||
if (!itemstack.isEmpty()
|
||||
&& this.gameMode.useItem(this.player, interactionhand) instanceof InteractionResult.Success interactionresult$success1) {
|
||||
if (interactionresult$success1.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
@@ -1791,6 +_,8 @@
|
||||
if (!heldItem.isEmpty() && this.gameMode.useItem(this.player, hand) instanceof InteractionResult.Success success) {
|
||||
if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
this.player.swing(hand);
|
||||
@@ -1789,6 +_,8 @@
|
||||
}
|
||||
|
||||
ProfilerFiller profilerfiller = Profiler.get();
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPreClientTick();
|
||||
+
|
||||
profilerfiller.push("gui");
|
||||
profiler.push("gui");
|
||||
this.textInputManager.tick();
|
||||
this.chatListener.tick();
|
||||
@@ -1873,6 +_,7 @@
|
||||
@@ -1871,6 +_,7 @@
|
||||
|
||||
this.tutorial.tick();
|
||||
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPreLevelTick(this.level, () -> true);
|
||||
try {
|
||||
this.level.tick(() -> true);
|
||||
} catch (Throwable throwable1) {
|
||||
@@ -1886,6 +_,7 @@
|
||||
} catch (Throwable var6) {
|
||||
@@ -1884,6 +_,7 @@
|
||||
|
||||
throw new ReportedException(crashreport1);
|
||||
throw new ReportedException(report);
|
||||
}
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPostLevelTick(this.level, () -> true);
|
||||
}
|
||||
|
||||
profilerfiller.popPush("animateTick");
|
||||
@@ -1910,6 +_,7 @@
|
||||
profilerfiller.popPush("keyboard");
|
||||
profiler.popPush("animateTick");
|
||||
@@ -1908,6 +_,7 @@
|
||||
profiler.popPush("keyboard");
|
||||
this.keyboardHandler.tick();
|
||||
profilerfiller.pop();
|
||||
profiler.pop();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPostClientTick();
|
||||
}
|
||||
|
||||
private boolean isLevelRunningNormally() {
|
||||
@@ -2140,6 +_,7 @@
|
||||
@@ -2138,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setLevel(final ClientLevel level) {
|
||||
@@ -309,15 +308,15 @@
|
||||
this.level = level;
|
||||
this.updateLevelInEngines(level);
|
||||
}
|
||||
@@ -2201,6 +_,7 @@
|
||||
IntegratedServer integratedserver = this.singleplayerServer;
|
||||
@@ -2199,6 +_,7 @@
|
||||
IntegratedServer server = this.singleplayerServer;
|
||||
this.singleplayerServer = null;
|
||||
this.gameRenderer.resetData();
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.firePlayerLogout(this.gameMode, this.player);
|
||||
this.gameMode = null;
|
||||
this.narrator.clear();
|
||||
this.clientLevelTeardownInProgress = true;
|
||||
@@ -2208,6 +_,7 @@
|
||||
@@ -2206,6 +_,7 @@
|
||||
try {
|
||||
if (this.level != null) {
|
||||
this.gui.onDisconnected();
|
||||
@@ -325,19 +324,19 @@
|
||||
}
|
||||
|
||||
this.level = null;
|
||||
@@ -2222,6 +_,7 @@
|
||||
@@ -2220,6 +_,7 @@
|
||||
}
|
||||
|
||||
profilerfiller.pop();
|
||||
profiler.pop();
|
||||
+ net.minecraftforge.client.ForgeHooksClient.handleClientLevelClosing(this.level);
|
||||
}
|
||||
|
||||
this.setScreenAndShow(screen);
|
||||
@@ -2374,6 +_,7 @@
|
||||
@@ -2372,6 +_,7 @@
|
||||
|
||||
private void pickBlockOrEntity() {
|
||||
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onClickInputPickBlock(this.options.keyPickItem)) return;
|
||||
boolean flag = this.hasControlDown();
|
||||
boolean includeData = this.hasControlDown();
|
||||
switch (this.hitResult) {
|
||||
case BlockHitResult blockhitresult:
|
||||
case BlockHitResult blockHitResult:
|
||||
@@ -4,65 +4,65 @@
|
||||
this.activeButton = null;
|
||||
}
|
||||
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPre(mousebuttoninfo, action)) return;
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPre(buttonInfo, action)) return;
|
||||
if (this.minecraft.getOverlay() == null) {
|
||||
if (this.minecraft.screen == null) {
|
||||
if (!this.mouseGrabbed && flag) {
|
||||
if (!this.mouseGrabbed && pressed) {
|
||||
@@ -106,7 +_,7 @@
|
||||
&& i - this.lastClick.time() < 250L
|
||||
&& currentTime - this.lastClick.time() < 250L
|
||||
&& this.lastClick.screen() == screen
|
||||
&& this.lastClickButton == mousebuttonevent.button();
|
||||
- if (screen.mouseClicked(mousebuttonevent, flag1)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseClicked(screen, d0, d1, mousebuttonevent, flag1)) {
|
||||
this.lastClick = new MouseHandler.LastClick(i, screen);
|
||||
this.lastClickButton = mousebuttoninfo.button();
|
||||
&& this.lastClickButton == event.button();
|
||||
- if (screen.mouseClicked(event, doubleClick)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseClicked(screen, xm, ym, event, doubleClick)) {
|
||||
this.lastClick = new MouseHandler.LastClick(currentTime, screen);
|
||||
this.lastClickButton = buttonInfo.button();
|
||||
return;
|
||||
@@ -121,7 +_,7 @@
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
- if (screen.mouseReleased(mousebuttonevent)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseReleased(screen, d0, d1, mousebuttonevent)) {
|
||||
- if (screen.mouseReleased(event)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseReleased(screen, xm, ym, event)) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
} catch (Throwable var17) {
|
||||
@@ -151,6 +_,7 @@
|
||||
KeyMapping.click(inputconstants$key);
|
||||
KeyMapping.click(mouseKey);
|
||||
}
|
||||
}
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(mousebuttoninfo, action);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(buttonInfo, action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +_,9 @@
|
||||
if (this.minecraft.screen != null) {
|
||||
double d3 = this.getScaledXPos(this.minecraft.getWindow());
|
||||
double d4 = this.getScaledYPos(this.minecraft.getWindow());
|
||||
- this.minecraft.screen.mouseScrolled(d3, d4, d1, d2);
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPre(this.minecraft.screen, d3, d4, d1, d2)) return;
|
||||
+ if (this.minecraft.screen.mouseScrolled(d3, d4, d1, d2)) return;
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPost(this.minecraft.screen, d3, d4, d1, d2);
|
||||
double xm = this.getScaledXPos(this.minecraft.getWindow());
|
||||
double ym = this.getScaledYPos(this.minecraft.getWindow());
|
||||
- this.minecraft.screen.mouseScrolled(xm, ym, scaledXOffset, scaledYOffset);
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPre(this.minecraft.screen, xm, ym, scaledXOffset, scaledYOffset)) return;
|
||||
+ if (this.minecraft.screen.mouseScrolled(xm, ym, scaledXOffset, scaledYOffset)) return;
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPost(this.minecraft.screen, xm, ym, scaledXOffset, scaledYOffset);
|
||||
this.minecraft.screen.afterMouseAction();
|
||||
} else if (this.minecraft.player != null) {
|
||||
Vector2i vector2i = this.scrollWheelHandler.onMouseScroll(d1, d2);
|
||||
Vector2i wheelXY = this.scrollWheelHandler.onMouseScroll(scaledXOffset, scaledYOffset);
|
||||
@@ -211,6 +_,7 @@
|
||||
}
|
||||
|
||||
int i = vector2i.y == 0 ? -vector2i.x : vector2i.y;
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseScroll(this, d1, d2)) return;
|
||||
int wheel = wheelXY.y == 0 ? -wheelXY.x : wheelXY.y;
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseScroll(this, scaledXOffset, scaledYOffset)) return;
|
||||
if (this.minecraft.player.isSpectator()) {
|
||||
if (this.minecraft.gui.getSpectatorGui().isMenuActive()) {
|
||||
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-i);
|
||||
@@ -315,7 +_,7 @@
|
||||
double d5 = getScaledYPos(window, this.accumulatedDY);
|
||||
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-wheel);
|
||||
@@ -317,7 +_,7 @@
|
||||
double dy = getScaledYPos(window, this.accumulatedDY);
|
||||
|
||||
try {
|
||||
- screen.mouseDragged(new MouseButtonEvent(d2, d3, this.activeButton), d4, d5);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenMouseDrag(screen, new MouseButtonEvent(d2, d3, this.activeButton), d4, d5);
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport1 = CrashReport.forThrowable(throwable, "mouseDragged event handler");
|
||||
screen.fillCrashDetails(crashreport1);
|
||||
@@ -400,6 +_,14 @@
|
||||
- screen.mouseDragged(new MouseButtonEvent(xm, ym, this.activeButton), dx, dy);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenMouseDrag(screen, new MouseButtonEvent(xm, ym, this.activeButton), dx, dy);
|
||||
} catch (Throwable var19) {
|
||||
CrashReport report = CrashReport.forThrowable(var19, "mouseDragged event handler");
|
||||
screen.fillCrashDetails(report);
|
||||
@@ -402,6 +_,14 @@
|
||||
|
||||
public double ypos() {
|
||||
return this.ypos;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Options.java
|
||||
+++ b/net/minecraft/client/Options.java
|
||||
@@ -921,6 +_,7 @@
|
||||
@@ -929,6 +_,7 @@
|
||||
);
|
||||
public boolean syncWrites;
|
||||
public boolean startedCleanly = true;
|
||||
@@ -8,15 +8,15 @@
|
||||
|
||||
public static boolean isSoundDeviceDefault(final String deviceName) {
|
||||
return deviceName.equals("");
|
||||
@@ -1396,6 +_,7 @@
|
||||
@@ -1404,6 +_,7 @@
|
||||
}
|
||||
|
||||
public Options(final Minecraft minecraft, final File workingDirectory) {
|
||||
+ setForgeKeybindProperties();
|
||||
this.minecraft = minecraft;
|
||||
this.optionsFile = new File(workingDirectory, "options.txt");
|
||||
boolean flag = Runtime.getRuntime().maxMemory() >= 1000000000L;
|
||||
@@ -1548,15 +_,28 @@
|
||||
boolean largeDistances = Runtime.getRuntime().maxMemory() >= 1000000000L;
|
||||
@@ -1556,15 +_,28 @@
|
||||
this.startedCleanly = access.process("startedCleanly", this.startedCleanly);
|
||||
access.process("musicToast", this.musicToast);
|
||||
access.process("musicFrequency", this.musicFrequency);
|
||||
@@ -26,27 +26,27 @@
|
||||
|
||||
+ // FORGE: split off to allow reloading keys after mod loading is done
|
||||
+ private void processOptionsKeysOnly(Options.FieldAccess access) {
|
||||
for (KeyMapping keymapping : this.keyMappings) {
|
||||
- String s = keymapping.saveString();
|
||||
+ String s = keymapping.saveString() + (keymapping.getKeyModifier() != net.minecraftforge.client.settings.KeyModifier.NONE ? ":" + keymapping.getKeyModifier() : "");
|
||||
String s1 = access.process("key_" + keymapping.getName(), s);
|
||||
if (!s.equals(s1)) {
|
||||
keymapping.setKey(InputConstants.getKey(s1));
|
||||
+ if (s1.indexOf(':') != -1) {
|
||||
+ String[] pts = s1.split(":");
|
||||
+ keymapping.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.valueFromString(pts[1]), InputConstants.getKey(pts[0]));
|
||||
for (KeyMapping keyMapping : this.keyMappings) {
|
||||
- String currentValue = keyMapping.saveString();
|
||||
+ String currentValue = keyMapping.saveString() + (keyMapping.getKeyModifier() != net.minecraftforge.client.settings.KeyModifier.NONE ? ":" + keyMapping.getKeyModifier() : "");
|
||||
String newValue = access.process("key_" + keyMapping.getName(), currentValue);
|
||||
if (!currentValue.equals(newValue)) {
|
||||
keyMapping.setKey(InputConstants.getKey(newValue));
|
||||
+ if (newValue.indexOf(':') != -1) {
|
||||
+ String[] pts = newValue.split(":");
|
||||
+ keyMapping.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.valueFromString(pts[1]), InputConstants.getKey(pts[0]));
|
||||
+ } else {
|
||||
+ keymapping.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.NONE, InputConstants.getKey(s1));
|
||||
+ keyMapping.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.NONE, InputConstants.getKey(newValue));
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ }
|
||||
|
||||
+ private void processOptionsEnd(Options.FieldAccess access) {
|
||||
for (SoundSource soundsource : SoundSource.values()) {
|
||||
access.process("soundCategory_" + soundsource.getName(), this.soundSourceVolumes.get(soundsource));
|
||||
for (SoundSource source : SoundSource.values()) {
|
||||
access.process("soundCategory_" + source.getName(), this.soundSourceVolumes.get(source));
|
||||
}
|
||||
@@ -1571,6 +_,10 @@
|
||||
@@ -1579,6 +_,10 @@
|
||||
}
|
||||
|
||||
public void load() {
|
||||
@@ -57,64 +57,64 @@
|
||||
try {
|
||||
if (!this.optionsFile.exists()) {
|
||||
return;
|
||||
@@ -1590,7 +_,8 @@
|
||||
@@ -1598,7 +_,8 @@
|
||||
}
|
||||
|
||||
final CompoundTag compoundtag1 = this.dataFix(compoundtag);
|
||||
final CompoundTag options = this.dataFix(rawOptions);
|
||||
- this.processOptions(
|
||||
+ java.util.function.Consumer<FieldAccess> processor = limited ? this::processOptionsKeysOnly : this::processOptions;
|
||||
+ processor.accept(
|
||||
new Options.FieldAccess() {
|
||||
{
|
||||
Objects.requireNonNull(Options.this);
|
||||
@@ -1672,6 +_,17 @@
|
||||
@@ -1680,6 +_,17 @@
|
||||
);
|
||||
compoundtag1.getString("fullscreenResolution").ifPresent(fullscreenResolution -> this.fullscreenVideoModeString = fullscreenResolution);
|
||||
options.getString("fullscreenResolution").ifPresent(fullscreenResolution -> this.fullscreenVideoModeString = fullscreenResolution);
|
||||
KeyMapping.resetMapping();
|
||||
+
|
||||
+ if (limited) {
|
||||
+ this.unknownKeys.clear();
|
||||
+ } else {
|
||||
+ var knownKeys = Arrays.stream(this.keyMappings).map(k -> "key_" + k.getName()).collect(Collectors.toSet());
|
||||
+ for (var entry : compoundtag1.entrySet()) {
|
||||
+ for (var entry : options.entrySet()) {
|
||||
+ if (entry.getKey().startsWith("key_") && entry.getValue().asString().isPresent() && !knownKeys.contains(entry.getKey()))
|
||||
+ this.unknownKeys.put(entry.getKey(), entry.getValue().asString().get());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
} catch (Exception exception) {
|
||||
LOGGER.error("Failed to load options", (Throwable)exception);
|
||||
} catch (Exception var7) {
|
||||
LOGGER.error("Failed to load options", (Throwable)var7);
|
||||
}
|
||||
@@ -1699,6 +_,7 @@
|
||||
@@ -1707,6 +_,7 @@
|
||||
public void save() {
|
||||
try (final PrintWriter printwriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.optionsFile), StandardCharsets.UTF_8))) {
|
||||
printwriter.println("version:" + SharedConstants.getCurrentVersion().dataVersion().version());
|
||||
try (final PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.optionsFile), StandardCharsets.UTF_8))) {
|
||||
writer.println("version:" + SharedConstants.getCurrentVersion().dataVersion().version());
|
||||
+ var seen = new java.util.HashSet<String>();
|
||||
this.processOptions(
|
||||
new Options.FieldAccess() {
|
||||
{
|
||||
@@ -1706,6 +_,7 @@
|
||||
@@ -1714,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void writePrefix(final String name) {
|
||||
+ seen.add(name);
|
||||
printwriter.print(name);
|
||||
printwriter.print(':');
|
||||
writer.print(name);
|
||||
writer.print(':');
|
||||
}
|
||||
@@ -1761,6 +_,12 @@
|
||||
if (s != null) {
|
||||
printwriter.println("fullscreenResolution:" + s);
|
||||
@@ -1769,6 +_,12 @@
|
||||
if (fullscreenVideoModeString != null) {
|
||||
writer.println("fullscreenResolution:" + fullscreenVideoModeString);
|
||||
}
|
||||
+ // Forge add any unknown keys so that Mods can add keybindings between vanilla loading/saving its config.
|
||||
+ for (var entry : this.unknownKeys.entrySet()) {
|
||||
+ if (!seen.contains(entry.getKey()))
|
||||
+ printwriter.println(entry.getKey() + ":" + entry.getValue());
|
||||
+ writer.println(entry.getKey() + ":" + entry.getValue());
|
||||
+ }
|
||||
+
|
||||
} catch (Exception exception) {
|
||||
LOGGER.error("Failed to save options", (Throwable)exception);
|
||||
} catch (Exception var6) {
|
||||
LOGGER.error("Failed to save options", (Throwable)var6);
|
||||
}
|
||||
@@ -1798,6 +_,7 @@
|
||||
@@ -1806,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void broadcastOptions() {
|
||||
@@ -122,7 +122,7 @@
|
||||
if (this.minecraft.player != null) {
|
||||
this.minecraft.player.connection.broadcastClientInformation(this.buildPlayerInformation());
|
||||
}
|
||||
@@ -1915,6 +_,23 @@
|
||||
@@ -1923,6 +_,23 @@
|
||||
|
||||
public static Component genericValueLabel(final Component caption, final int value) {
|
||||
return genericValueLabel(caption, Component.literal(Integer.toString(value)));
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
--- a/net/minecraft/client/Screenshot.java
|
||||
+++ b/net/minecraft/client/Screenshot.java
|
||||
@@ -45,6 +_,13 @@
|
||||
file2 = new File(file1, forceName);
|
||||
@@ -44,6 +_,13 @@
|
||||
file = new File(picDir, forceName);
|
||||
}
|
||||
|
||||
+ var event = new net.minecraftforge.client.event.ScreenshotEvent(image, file2);
|
||||
+ var event = new net.minecraftforge.client.event.ScreenshotEvent(image, file);
|
||||
+ if (net.minecraftforge.client.event.ScreenshotEvent.BUS.post(event)) {
|
||||
+ callback.accept(event.getCancelMessage());
|
||||
+ return;
|
||||
@@ -14,19 +14,19 @@
|
||||
Util.ioPool()
|
||||
.execute(
|
||||
() -> {
|
||||
@@ -52,10 +_,13 @@
|
||||
NativeImage nativeimage = image;
|
||||
@@ -51,10 +_,13 @@
|
||||
NativeImage twrVar0$ = image;
|
||||
|
||||
try {
|
||||
- image.writeToFile(file2);
|
||||
- Component component = Component.literal(file2.getName())
|
||||
- image.writeToFile(file);
|
||||
- Component component = Component.literal(file.getName())
|
||||
+ image.writeToFile(outputFile);
|
||||
+ Component component = Component.literal(outputFile.getName())
|
||||
.withStyle(ChatFormatting.UNDERLINE)
|
||||
.withStyle(s -> s.withClickEvent(new ClickEvent.OpenFile(file2.getAbsoluteFile())));
|
||||
.withStyle(s -> s.withClickEvent(new ClickEvent.OpenFile(file.getAbsoluteFile())));
|
||||
+ if (event.getResultMessage() != null)
|
||||
+ callback.accept(event.getResultMessage());
|
||||
+ else
|
||||
callback.accept(Component.translatable("screenshot.success", component));
|
||||
} catch (Throwable throwable1) {
|
||||
} catch (Throwable var7) {
|
||||
if (image != null) {
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/net/minecraft/client/color/block/BlockColors.java
|
||||
+++ b/net/minecraft/client/color/block/BlockColors.java
|
||||
@@ -45,6 +_,7 @@
|
||||
blockcolors.register(List.of(BlockTintSources.constant(-2046180)), Blocks.ATTACHED_MELON_STEM, Blocks.ATTACHED_PUMPKIN_STEM);
|
||||
blockcolors.register(List.of(BlockTintSources.stem()), Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
|
||||
blockcolors.register(List.of(BlockTintSources.constant(-9321636, -14647248)), Blocks.LILY_PAD);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onBlockColorsInit(blockcolors);
|
||||
return blockcolors;
|
||||
colors.register(List.of(BlockTintSources.constant(-2046180)), Blocks.ATTACHED_MELON_STEM, Blocks.ATTACHED_PUMPKIN_STEM);
|
||||
colors.register(List.of(BlockTintSources.stem()), Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
|
||||
colors.register(List.of(BlockTintSources.constant(-9321636, -14647248)), Blocks.LILY_PAD);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onBlockColorsInit(colors);
|
||||
return colors;
|
||||
}
|
||||
|
||||
@@ -57,6 +_,8 @@
|
||||
return layer >= list.size() ? null : list.get(layer);
|
||||
return layer >= layers.size() ? null : layers.get(layer);
|
||||
}
|
||||
|
||||
+ /** @deprecated Register via {@link net.minecraftforge.client.event.RegisterColorHandlersEvent.Block} */
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
--- a/net/minecraft/client/data/Main.java
|
||||
+++ b/net/minecraft/client/data/Main.java
|
||||
@@ -28,13 +_,18 @@
|
||||
OptionSpec<Void> optionspec1 = optionparser.accepts("client", "Include client generators");
|
||||
OptionSpec<Void> optionspec2 = optionparser.accepts("all", "Include all generators");
|
||||
OptionSpec<String> optionspec3 = optionparser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
|
||||
+ OptionSpec<String> inputSpec = optionparser.accepts("input", "Input folder").withRequiredArg();
|
||||
+ var loader = net.minecraftforge.data.loading.DatagenModLoader.setup(optionparser, true);
|
||||
OptionSet optionset = optionparser.parse(args);
|
||||
- if (!optionset.has(optionspec) && optionset.hasOptions()) {
|
||||
+ if (!optionset.has(optionspec) && optionset.hasOptions() && loader.hasArgs(optionset)) {
|
||||
+ var input = optionset.valuesOf(inputSpec).stream().map(Paths::get).toList();
|
||||
Path path = Paths.get(optionspec3.value(optionset));
|
||||
boolean flag = optionset.has(optionspec2);
|
||||
boolean flag1 = flag || optionset.has(optionspec1);
|
||||
OptionSpec<Void> clientOption = parser.accepts("client", "Include client generators");
|
||||
OptionSpec<Void> allOption = parser.accepts("all", "Include all generators");
|
||||
OptionSpec<String> outputOption = parser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
|
||||
+ OptionSpec<String> inputSpec = parser.accepts("input", "Input folder").withRequiredArg();
|
||||
+ var loader = net.minecraftforge.data.loading.DatagenModLoader.setup(parser, true);
|
||||
OptionSet optionSet = parser.parse(args);
|
||||
- if (!optionSet.has(helpOption) && optionSet.hasOptions()) {
|
||||
+ if (!optionSet.has(helpOption) && optionSet.hasOptions() && loader.hasArgs(optionSet)) {
|
||||
+ var input = optionSet.valuesOf(inputSpec).stream().map(Paths::get).toList();
|
||||
Path output = Paths.get(outputOption.value(optionSet));
|
||||
boolean allOptions = optionSet.has(allOption);
|
||||
boolean client = allOptions || optionSet.has(clientOption);
|
||||
Bootstrap.bootStrap();
|
||||
ClientBootstrap.bootstrap();
|
||||
+ if (!loader.run(optionset, path, input, flag, flag1, flag, flag))
|
||||
+ if (!loader.run(optionSet, output, input, allOptions, client, allOptions, allOptions))
|
||||
+ return;
|
||||
DataGenerator datagenerator = new DataGenerator.Cached(path, SharedConstants.getCurrentVersion(), true);
|
||||
addClientProviders(datagenerator, flag1);
|
||||
datagenerator.run();
|
||||
DataGenerator generator = new DataGenerator.Cached(output, SharedConstants.getCurrentVersion(), true);
|
||||
addClientProviders(generator, client);
|
||||
generator.run();
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
@@ -922,6 +_,9 @@
|
||||
@@ -909,6 +_,9 @@
|
||||
this.declareCustomModelItem(Items.COD);
|
||||
this.declareCustomModelItem(Items.FEATHER);
|
||||
this.declareCustomModelItem(Items.LEAD);
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
--- a/net/minecraft/client/data/models/ModelProvider.java
|
||||
+++ b/net/minecraft/client/data/models/ModelProvider.java
|
||||
@@ -44,11 +_,11 @@
|
||||
@@ -43,11 +_,11 @@
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> run(final CachedOutput cache) {
|
||||
- ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector();
|
||||
- ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector();
|
||||
+ ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector(this::getKnownItems);
|
||||
+ ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector(this::getKnownBlocks);
|
||||
ModelProvider.SimpleModelCollector modelprovider$simplemodelcollector = new ModelProvider.SimpleModelCollector();
|
||||
- new BlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
- new ItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
+ getBlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
+ getItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
modelprovider$blockstategeneratorcollector.validate();
|
||||
modelprovider$iteminfocollector.finalizeAndValidate();
|
||||
- ModelProvider.ItemInfoCollector itemModels = new ModelProvider.ItemInfoCollector();
|
||||
- ModelProvider.BlockStateGeneratorCollector blockStateGenerators = new ModelProvider.BlockStateGeneratorCollector();
|
||||
+ ModelProvider.ItemInfoCollector itemModels = new ModelProvider.ItemInfoCollector(this::getKnownItems);
|
||||
+ ModelProvider.BlockStateGeneratorCollector blockStateGenerators = new ModelProvider.BlockStateGeneratorCollector(this::getKnownBlocks);
|
||||
ModelProvider.SimpleModelCollector simpleModels = new ModelProvider.SimpleModelCollector();
|
||||
- new BlockModelGenerators(blockStateGenerators, itemModels, simpleModels).run();
|
||||
- new ItemModelGenerators(itemModels, simpleModels).run();
|
||||
+ getBlockModelGenerators(blockStateGenerators, itemModels, simpleModels).run();
|
||||
+ getItemModelGenerators(itemModels, simpleModels).run();
|
||||
blockStateGenerators.validate();
|
||||
itemModels.finalizeAndValidate();
|
||||
return CompletableFuture.allOf(
|
||||
@@ -58,6 +_,22 @@
|
||||
@@ -57,6 +_,22 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
@Override
|
||||
public final String getName() {
|
||||
return "Model Definitions";
|
||||
@@ -66,6 +_,15 @@
|
||||
@@ -65,6 +_,15 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class BlockStateGeneratorCollector implements Consumer<BlockModelDefinitionGenerator> {
|
||||
private final Map<Block, BlockModelDefinitionGenerator> generators = new HashMap<>();
|
||||
@@ -55,17 +55,17 @@
|
||||
|
||||
public void accept(final BlockModelDefinitionGenerator generator) {
|
||||
Block block = generator.block();
|
||||
@@ -76,8 +_,7 @@
|
||||
@@ -75,8 +_,7 @@
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
- List<Identifier> list = BuiltInRegistries.BLOCK
|
||||
- List<Identifier> missingDefinitions = BuiltInRegistries.BLOCK
|
||||
- .listElements()
|
||||
+ List<Identifier> list = known.get().map(Block::builtInRegistryHolder)
|
||||
+ List<Identifier> missingDefinitions = known.get().map(Block::builtInRegistryHolder)
|
||||
.filter(e -> !this.generators.containsKey(e.value()))
|
||||
.map(e -> e.key().identifier())
|
||||
.toList();
|
||||
@@ -97,6 +_,15 @@
|
||||
@@ -96,6 +_,15 @@
|
||||
public static class ItemInfoCollector implements ItemModelOutput {
|
||||
private final Map<Item, ClientItem> itemInfos = new HashMap<>();
|
||||
private final Map<Item, Item> copies = new HashMap<>();
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
@Override
|
||||
public void accept(final Item item, final ItemModel.Unbaked model, final ClientItem.Properties properties) {
|
||||
@@ -115,7 +_,7 @@
|
||||
@@ -114,7 +_,7 @@
|
||||
this.copies.put(acceptor, donor);
|
||||
}
|
||||
|
||||
@@ -89,23 +89,23 @@
|
||||
+ public void generateDefaultBlockModels() {
|
||||
BuiltInRegistries.ITEM.forEach(item -> {
|
||||
if (!this.copies.containsKey(item)) {
|
||||
if (item instanceof BlockItem blockitem && !this.itemInfos.containsKey(blockitem)) {
|
||||
@@ -124,6 +_,8 @@
|
||||
if (item instanceof BlockItem blockItem && !this.itemInfos.containsKey(blockItem)) {
|
||||
@@ -123,6 +_,8 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
+ }
|
||||
+ public void finalizeAndValidate() {
|
||||
this.copies.forEach((acceptor, donor) -> {
|
||||
ClientItem clientitem = this.itemInfos.get(donor);
|
||||
if (clientitem == null) {
|
||||
@@ -132,8 +_,8 @@
|
||||
this.register(acceptor, clientitem);
|
||||
ClientItem donorInfo = this.itemInfos.get(donor);
|
||||
if (donorInfo == null) {
|
||||
@@ -131,8 +_,8 @@
|
||||
this.register(acceptor, donorInfo);
|
||||
}
|
||||
});
|
||||
- List<Identifier> list = BuiltInRegistries.ITEM
|
||||
- List<Identifier> missingDefinitions = BuiltInRegistries.ITEM
|
||||
- .listElements()
|
||||
+ List<Identifier> list = known.get()
|
||||
+ List<Identifier> missingDefinitions = known.get()
|
||||
+ .map(item -> item.builtInRegistryHolder())
|
||||
.filter(e -> !this.itemInfos.containsKey(e.value()))
|
||||
.map(e -> e.key().identifier())
|
||||
|
||||
@@ -29,74 +29,87 @@
|
||||
this.extractCameraOverlays(graphics, deltaTracker);
|
||||
this.extractCrosshair(graphics, deltaTracker);
|
||||
@@ -385,7 +_,7 @@
|
||||
int i = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
|
||||
int j = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
|
||||
int mouseX = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
|
||||
int mouseY = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
|
||||
graphics.nextStratum();
|
||||
- this.chat.extractRenderState(graphics, this.getFont(), this.tickCount, i, j, ChatComponent.DisplayMode.BACKGROUND, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(graphics, this.chat, window, i, j, this.tickCount, this.getFont());
|
||||
- this.chat.extractRenderState(graphics, this.getFont(), this.tickCount, mouseX, mouseY, ChatComponent.DisplayMode.BACKGROUND, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(graphics, this.chat, window, mouseX, mouseY, this.tickCount, this.getFont());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,6 +_,8 @@
|
||||
@@ -478,6 +_,8 @@
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
|
||||
Holder<MobEffect> holder = mobeffectinstance.getEffect();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(mobeffectinstance);
|
||||
+ if (!renderer.isVisibleInGui(mobeffectinstance)) continue;
|
||||
if (mobeffectinstance.showIcon()) {
|
||||
int k = graphics.guiWidth();
|
||||
int l = 1;
|
||||
@@ -505,6 +_,7 @@
|
||||
for (MobEffectInstance instance : Ordering.natural().reverse().sortedCopy(activeEffects)) {
|
||||
Holder<MobEffect> effect = instance.getEffect();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(instance);
|
||||
+ if (!renderer.isVisibleInGui(instance)) continue;
|
||||
if (instance.showIcon()) {
|
||||
int x = graphics.guiWidth();
|
||||
int y = 1;
|
||||
@@ -508,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (renderer.extractGuiIcon(mobeffectinstance, this, graphics, k, l, 0, f)) continue;
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, getMobEffectSprite(holder), k + 3, l + 3, 18, 18, ARGB.white(f));
|
||||
+ if (renderer.extractGuiIcon(instance, this, graphics, x, y, 0, alpha)) continue;
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, getMobEffectSprite(effect), x + 3, y + 3, 18, 18, ARGB.white(alpha));
|
||||
}
|
||||
}
|
||||
@@ -605,6 +_,10 @@
|
||||
@@ -610,15 +_,37 @@
|
||||
}
|
||||
|
||||
public void extractSelectedItemName(final GuiGraphicsExtractor graphics) {
|
||||
+ renderSelectedItemName(graphics, 0);
|
||||
+ }
|
||||
+
|
||||
+ // Forge: Maintain vanilla parity during FLD#BACKGROUND
|
||||
+ public final void updateContextualInfo(final GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) {
|
||||
+ Gui.ContextualInfo nextContextualInfo = this.nextContextualInfoState();
|
||||
+ if (nextContextualInfo != this.contextualInfoBar.getKey()) {
|
||||
+ this.contextualInfoBar = Pair.of(nextContextualInfo, this.contextualInfoBarRenderers.get(nextContextualInfo).get());
|
||||
+ }
|
||||
+
|
||||
+ this.contextualInfoBar.getValue().extractBackground(graphics, deltaTracker);
|
||||
+ }
|
||||
+ // Forge: Same as above but for FLD#CONTEXTUAL_INFO
|
||||
+ public final void extractContextualInfoState(final GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) {
|
||||
+ this.contextualInfoBar.getValue().extractRenderState(graphics, deltaTracker);
|
||||
+ }
|
||||
+
|
||||
+ public void renderSelectedItemName(final GuiGraphicsExtractor graphics, int yShift) {
|
||||
if (this.toolHighlightTimer > 0 && !this.lastToolHighlight.isEmpty()) {
|
||||
MutableComponent mutablecomponent = Component.empty()
|
||||
.append(this.lastToolHighlight.getHoverName())
|
||||
@@ -613,9 +_,13 @@
|
||||
mutablecomponent.withStyle(ChatFormatting.ITALIC);
|
||||
MutableComponent str = Component.empty().append(this.lastToolHighlight.getHoverName()).withStyle(this.lastToolHighlight.getRarity().color());
|
||||
if (this.lastToolHighlight.has(DataComponents.CUSTOM_NAME)) {
|
||||
str.withStyle(ChatFormatting.ITALIC);
|
||||
}
|
||||
|
||||
- int i = this.getFont().width(mutablecomponent);
|
||||
+ Component highlightTip = this.lastToolHighlight.getHighlightTip(mutablecomponent);
|
||||
- int strWidth = this.getFont().width(str);
|
||||
+ Component highlightTip = this.lastToolHighlight.getHighlightTip(str);
|
||||
+ Font font = net.minecraftforge.client.extensions.common.IClientItemExtensions.of(lastToolHighlight).getFont(lastToolHighlight, net.minecraftforge.client.extensions.common.IClientItemExtensions.FontContext.SELECTED_ITEM_NAME);
|
||||
+ if (font == null)
|
||||
+ font = this.getFont();
|
||||
+ int i = font.width(highlightTip);
|
||||
int j = (graphics.guiWidth() - i) / 2;
|
||||
- int k = graphics.guiHeight() - 59;
|
||||
+ int k = graphics.guiHeight() - Math.max(yShift, 59);
|
||||
+ int strWidth = font.width(highlightTip);
|
||||
int x = (graphics.guiWidth() - strWidth) / 2;
|
||||
- int y = graphics.guiHeight() - 59;
|
||||
+ int y = graphics.guiHeight() - Math.max(yShift, 59);
|
||||
if (!this.minecraft.gameMode.canHurtPlayer()) {
|
||||
k += 14;
|
||||
y += 14;
|
||||
}
|
||||
@@ -626,7 +_,7 @@
|
||||
@@ -629,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (l > 0) {
|
||||
- graphics.textWithBackdrop(this.getFont(), mutablecomponent, j, k, i, ARGB.white(l));
|
||||
+ graphics.textWithBackdrop(font, highlightTip, j, k, i, ARGB.white(l));
|
||||
if (alpha > 0) {
|
||||
- graphics.textWithBackdrop(this.getFont(), str, x, y, strWidth, ARGB.white(alpha));
|
||||
+ graphics.textWithBackdrop(font, highlightTip, x, y, strWidth, ARGB.white(alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1165,7 +_,9 @@
|
||||
@@ -1195,7 +_,9 @@
|
||||
this.toolHighlightTimer = 0;
|
||||
} else if (this.lastToolHighlight.isEmpty()
|
||||
|| !itemstack.is(this.lastToolHighlight.getItem())
|
||||
- || !itemstack.getHoverName().equals(this.lastToolHighlight.getHoverName())) {
|
||||
+ || !itemstack.getHoverName().equals(this.lastToolHighlight.getHoverName())
|
||||
+ || !itemstack.getHighlightTip(itemstack.getHoverName()).equals(lastToolHighlight.getHighlightTip(lastToolHighlight.getHoverName()))
|
||||
|| !selected.is(this.lastToolHighlight.getItem())
|
||||
- || !selected.getHoverName().equals(this.lastToolHighlight.getHoverName())) {
|
||||
+ || !selected.getHoverName().equals(this.lastToolHighlight.getHoverName())
|
||||
+ || !selected.getHighlightTip(selected.getHoverName()).equals(lastToolHighlight.getHighlightTip(lastToolHighlight.getHoverName()))
|
||||
+ ) {
|
||||
this.toolHighlightTimer = (int)(40.0 * this.minecraft.options.notificationDisplayTime().get());
|
||||
} else if (this.toolHighlightTimer > 0) {
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
private static final int EXTRA_SPACE_AFTER_FIRST_TOOLTIP_LINE = 2;
|
||||
private final Minecraft minecraft;
|
||||
private final Matrix3x2fStack pose;
|
||||
@@ -867,6 +_,7 @@
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item");
|
||||
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered");
|
||||
crashreportcategory.setDetail("Item Type", () -> String.valueOf(itemStack.getItem()));
|
||||
+ crashreportcategory.setDetail("Registry Name", () -> String.valueOf(net.minecraftforge.registries.ForgeRegistries.ITEMS.getKey(itemStack.getItem())));
|
||||
crashreportcategory.setDetail("Item Components", () -> String.valueOf(itemStack.getComponents()));
|
||||
crashreportcategory.setDetail("Item Foil", () -> String.valueOf(itemStack.hasFoil()));
|
||||
throw new ReportedException(crashreport);
|
||||
@@ -893,6 +_,7 @@
|
||||
@@ -914,6 +_,7 @@
|
||||
CrashReport report = CrashReport.forThrowable(var11, "Rendering item");
|
||||
CrashReportCategory category = report.addCategory("Item being rendered");
|
||||
category.setDetail("Item Type", () -> String.valueOf(itemStack.getItem()));
|
||||
+ category.setDetail("Registry Name", () -> String.valueOf(net.minecraftforge.registries.ForgeRegistries.ITEMS.getKey(itemStack.getItem())));
|
||||
category.setDetail("Item Components", () -> String.valueOf(itemStack.getComponents()));
|
||||
category.setDetail("Item Foil", () -> String.valueOf(itemStack.hasFoil()));
|
||||
throw new ReportedException(report);
|
||||
@@ -940,6 +_,7 @@
|
||||
this.itemCooldown(itemStack, x, y);
|
||||
this.itemCount(font, itemStack, x, y, countText);
|
||||
this.pose.popMatrix();
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,16 +_,25 @@
|
||||
@@ -1112,16 +_,25 @@
|
||||
this.setTooltipForNextFrame(this.minecraft.font, formattedCharSequences, DefaultTooltipPositioner.INSTANCE, x, y, false);
|
||||
}
|
||||
|
||||
@@ -51,17 +51,20 @@
|
||||
public void setTooltipForNextFrame(
|
||||
final Font font,
|
||||
final List<Component> texts,
|
||||
@@ -1087,8 +_,7 @@
|
||||
@@ -1130,11 +_,7 @@
|
||||
final int yo,
|
||||
final @Nullable Identifier style
|
||||
) {
|
||||
- List<ClientTooltipComponent> list = texts.stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).collect(Util.toMutableList());
|
||||
- optionalImage.ifPresent(image -> list.add(list.isEmpty() ? 0 : 1, ClientTooltipComponent.create(image)));
|
||||
+ List<ClientTooltipComponent> list = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, texts, optionalImage, xo, guiWidth(), guiHeight(), font);
|
||||
this.setTooltipForNextFrameInternal(font, list, xo, yo, DefaultTooltipPositioner.INSTANCE, style, false);
|
||||
- List<ClientTooltipComponent> components = texts.stream()
|
||||
- .map(Component::getVisualOrderText)
|
||||
- .map(ClientTooltipComponent::create)
|
||||
- .collect(Util.toMutableList());
|
||||
- optionalImage.ifPresent(image -> components.add(components.isEmpty() ? 0 : 1, ClientTooltipComponent.create(image)));
|
||||
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, texts, optionalImage, xo, guiWidth(), guiHeight(), font);
|
||||
this.setTooltipForNextFrameInternal(font, components, xo, yo, DefaultTooltipPositioner.INSTANCE, style, false);
|
||||
}
|
||||
|
||||
@@ -1116,7 +_,22 @@
|
||||
@@ -1162,7 +_,22 @@
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(final Font font, final List<Component> lines, final int xo, final int yo) {
|
||||
@@ -85,7 +88,7 @@
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(final Font font, final List<Component> lines, final int xo, final int yo, final @Nullable Identifier style) {
|
||||
@@ -1167,10 +_,16 @@
|
||||
@@ -1213,10 +_,16 @@
|
||||
) {
|
||||
if (!lines.isEmpty()) {
|
||||
if (this.deferredTooltip == null || replaceExisting) {
|
||||
@@ -103,7 +106,7 @@
|
||||
|
||||
public void tooltip(
|
||||
final Font font,
|
||||
@@ -1178,13 +_,16 @@
|
||||
@@ -1224,13 +_,16 @@
|
||||
final int xo,
|
||||
final int yo,
|
||||
final ClientTooltipPositioner positioner,
|
||||
@@ -113,48 +116,48 @@
|
||||
) {
|
||||
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(itemstack, this, xo, yo, guiWidth(), guiHeight(), lines, font, positioner, style);
|
||||
+ if (preEvent == null) return;
|
||||
int i = 0;
|
||||
int j = lines.size() == 1 ? -2 : 0;
|
||||
int textWidth = 0;
|
||||
int tempHeight = lines.size() == 1 ? -2 : 0;
|
||||
|
||||
for (ClientTooltipComponent clienttooltipcomponent : lines) {
|
||||
- int k = clienttooltipcomponent.getWidth(font);
|
||||
+ int k = clienttooltipcomponent.getWidth(preEvent.getFont());
|
||||
if (k > i) {
|
||||
i = k;
|
||||
for (ClientTooltipComponent line : lines) {
|
||||
- int lineWidth = line.getWidth(font);
|
||||
+ int lineWidth = line.getWidth(preEvent.getFont());
|
||||
if (lineWidth > textWidth) {
|
||||
textWidth = lineWidth;
|
||||
}
|
||||
@@ -1194,25 +_,25 @@
|
||||
@@ -1240,25 +_,25 @@
|
||||
|
||||
int l1 = i;
|
||||
int i2 = j;
|
||||
- Vector2ic vector2ic = positioner.positionTooltip(this.guiWidth(), this.guiHeight(), xo, yo, i, j);
|
||||
+ Vector2ic vector2ic = positioner.positionTooltip(this.guiWidth(), this.guiHeight(), preEvent.getX(), preEvent.getY(), i, j);
|
||||
int l = vector2ic.x();
|
||||
int i1 = vector2ic.y();
|
||||
int w = textWidth;
|
||||
int h = tempHeight;
|
||||
- Vector2ic positionedTooltip = positioner.positionTooltip(this.guiWidth(), this.guiHeight(), xo, yo, textWidth, tempHeight);
|
||||
+ Vector2ic positionedTooltip = positioner.positionTooltip(this.guiWidth(), this.guiHeight(), preEvent.getX(), preEvent.getY(), textWidth, tempHeight);
|
||||
int x = positionedTooltip.x();
|
||||
int y = positionedTooltip.y();
|
||||
this.pose.pushMatrix();
|
||||
- TooltipRenderUtil.extractTooltipBackground(this, l, i1, i, j, style);
|
||||
+ TooltipRenderUtil.extractTooltipBackground(this, l, i1, i, j, preEvent.getBackground());
|
||||
int j1 = i1;
|
||||
- TooltipRenderUtil.extractTooltipBackground(this, x, y, textWidth, tempHeight, style);
|
||||
+ TooltipRenderUtil.extractTooltipBackground(this, x, y, textWidth, tempHeight, preEvent.getBackground());
|
||||
int localY = y;
|
||||
|
||||
for (int k1 = 0; k1 < lines.size(); k1++) {
|
||||
ClientTooltipComponent clienttooltipcomponent1 = lines.get(k1);
|
||||
- clienttooltipcomponent1.extractText(this, font, l, j1);
|
||||
- j1 += clienttooltipcomponent1.getHeight(font) + (k1 == 0 ? 2 : 0);
|
||||
+ clienttooltipcomponent1.extractText(this, preEvent.getFont(), l, j1);
|
||||
+ j1 += clienttooltipcomponent1.getHeight(preEvent.getFont()) + (k1 == 0 ? 2 : 0);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
ClientTooltipComponent line = lines.get(i);
|
||||
- line.extractText(this, font, x, localY);
|
||||
- localY += line.getHeight(font) + (i == 0 ? 2 : 0);
|
||||
+ line.extractText(this, preEvent.getFont(), x, localY);
|
||||
+ localY += line.getHeight(preEvent.getFont()) + (i == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
j1 = i1;
|
||||
localY = y;
|
||||
|
||||
for (int j2 = 0; j2 < lines.size(); j2++) {
|
||||
ClientTooltipComponent clienttooltipcomponent2 = lines.get(j2);
|
||||
- clienttooltipcomponent2.extractImage(font, l, j1, l1, i2, this);
|
||||
- j1 += clienttooltipcomponent2.getHeight(font) + (j2 == 0 ? 2 : 0);
|
||||
+ clienttooltipcomponent2.extractImage(preEvent.getFont(), l, j1, l1, i2, this);
|
||||
+ j1 += clienttooltipcomponent2.getHeight(preEvent.getFont()) + (j2 == 0 ? 2 : 0);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
ClientTooltipComponent line = lines.get(i);
|
||||
- line.extractImage(font, x, localY, w, h, this);
|
||||
- localY += line.getHeight(font) + (i == 0 ? 2 : 0);
|
||||
+ line.extractImage(preEvent.getFont(), x, localY, w, h, this);
|
||||
+ localY += line.getHeight(preEvent.getFont()) + (i == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
this.pose.popMatrix();
|
||||
@@ -1287,6 +_,14 @@
|
||||
@@ -1333,6 +_,14 @@
|
||||
|
||||
private ActiveTextCollector.Parameters createDefaultTextParameters(final float opacity) {
|
||||
return new ActiveTextCollector.Parameters(new Matrix3x2f(this.pose), opacity, this.scissorStack.peek());
|
||||
|
||||
+13
-13
@@ -2,19 +2,19 @@
|
||||
+++ b/net/minecraft/client/gui/components/BossHealthOverlay.java
|
||||
@@ -68,13 +_,16 @@
|
||||
|
||||
for (LerpingBossEvent lerpingbossevent : this.events.values()) {
|
||||
int k = i / 2 - 91;
|
||||
+ var event = net.minecraftforge.client.ForgeHooksClient.onCustomizeBossEventProgress(graphics, this.minecraft.getWindow(), lerpingbossevent, k, j, 10 + this.minecraft.font.lineHeight);
|
||||
+ if (event != null) {
|
||||
this.extractBar(graphics, k, j, lerpingbossevent);
|
||||
Component component = lerpingbossevent.getName();
|
||||
int l = this.minecraft.font.width(component);
|
||||
int i1 = i / 2 - l / 2;
|
||||
int j1 = j - 9;
|
||||
graphics.text(this.minecraft.font, component, i1, j1, -1);
|
||||
- j += 10 + 9;
|
||||
for (LerpingBossEvent event : this.events.values()) {
|
||||
int xLeft = screenWidth / 2 - 91;
|
||||
+ var progressEvent = net.minecraftforge.client.ForgeHooksClient.onCustomizeBossEventProgress(graphics, this.minecraft.getWindow(), event, xLeft, yOffset, 10 + this.minecraft.font.lineHeight);
|
||||
+ if (progressEvent != null) {
|
||||
this.extractBar(graphics, xLeft, yOffset, event);
|
||||
Component msg = event.getName();
|
||||
int width = this.minecraft.font.width(msg);
|
||||
int x = screenWidth / 2 - width / 2;
|
||||
int y = yOffset - 9;
|
||||
graphics.text(this.minecraft.font, msg, x, y, -1);
|
||||
- yOffset += 10 + 9;
|
||||
+ }
|
||||
+ j += event.getIncrement();
|
||||
if (j >= graphics.guiHeight() / 3) {
|
||||
+ yOffset += progressEvent.getIncrement();
|
||||
if (yOffset >= graphics.guiHeight() / 3) {
|
||||
break;
|
||||
}
|
||||
+4
-4
@@ -2,9 +2,9 @@
|
||||
+++ b/net/minecraft/client/gui/components/debug/DebugEntryLookingAtEntity.java
|
||||
@@ -29,6 +_,7 @@
|
||||
if (entity != null) {
|
||||
list.add(ChatFormatting.UNDERLINE + "Targeted Entity");
|
||||
list.add(entity.typeHolder().getRegisteredName());
|
||||
+ entity.getType().builtInRegistryHolder().tags().forEach(t -> list.add("#" + t.location()));
|
||||
result.add(ChatFormatting.UNDERLINE + "Targeted Entity");
|
||||
result.add(entity.typeHolder().getRegisteredName());
|
||||
+ entity.getType().builtInRegistryHolder().tags().forEach(t -> result.add("#" + t.location()));
|
||||
}
|
||||
|
||||
displayer.addToGroup(GROUP, list);
|
||||
displayer.addToGroup(GROUP, result);
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
+++ b/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
@@ -131,6 +_,7 @@
|
||||
builder.put((Class<? extends PictureInPictureRenderState>)pictureinpicturerenderer.getRenderStateClass(), pictureinpicturerenderer);
|
||||
@@ -130,6 +_,7 @@
|
||||
builder.put((Class<? extends PictureInPictureRenderState>)pictureInPictureRenderer.getRenderStateClass(), pictureInPictureRenderer);
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onRegisterPictureInPictureRenderers(pictureInPictureRenderers, bufferSource, builder);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@@ -114,6 +_,8 @@
|
||||
}
|
||||
|
||||
if (optional.isEmpty()) {
|
||||
if (resolvedAddress.isEmpty()) {
|
||||
+ ConnectScreen.LOGGER.error("Couldn't connect to server: Unknown host \"{}\"", hostAndPort.getHost());
|
||||
+ net.minecraftforge.network.DualStackUtils.logInitialPreferences();
|
||||
minecraft.execute(
|
||||
|
||||
@@ -8,24 +8,24 @@
|
||||
+
|
||||
@Override
|
||||
public void extractRenderState(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final float a) {
|
||||
int i = graphics.guiWidth();
|
||||
int width = graphics.guiWidth();
|
||||
@@ -103,6 +_,7 @@
|
||||
f2 = 1.0F;
|
||||
logoAlpha = 1.0F;
|
||||
}
|
||||
|
||||
+ if (extractContentRenderState(graphics, f2)) {
|
||||
int k2 = (int)(graphics.guiWidth() * 0.5);
|
||||
int i1 = (int)(graphics.guiHeight() * 0.5);
|
||||
double d0 = Math.min(graphics.guiWidth() * 0.75, (double)graphics.guiHeight()) * 0.25;
|
||||
@@ -118,6 +_,7 @@
|
||||
if (f < 1.0F) {
|
||||
this.extractProgressBar(graphics, i / 2 - k1, i2 - 5, i / 2 + k1, i2 + 5, 1.0F - Mth.clamp(f, 0.0F, 1.0F));
|
||||
+ if (extractContentRenderState(graphics, logoAlpha)) {
|
||||
int contentX = (int)(graphics.guiWidth() * 0.5);
|
||||
int logoY = (int)(graphics.guiHeight() * 0.5);
|
||||
double logoHeight = Math.min(graphics.guiWidth() * 0.75, (double)graphics.guiHeight()) * 0.25;
|
||||
@@ -148,6 +_,7 @@
|
||||
graphics, width / 2 - logoWidthHalf, barY - 5, width / 2 + logoWidthHalf, barY + 5, 1.0F - Mth.clamp(fadeOutAnim, 0.0F, 1.0F)
|
||||
);
|
||||
}
|
||||
+ }
|
||||
|
||||
if (f >= 2.0F) {
|
||||
if (fadeOutAnim >= 2.0F) {
|
||||
this.minecraft.setOverlay(null);
|
||||
@@ -127,6 +_,7 @@
|
||||
@@ -157,6 +_,7 @@
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.fadeOutStart == -1L && this.reload.isDone() && this.isReadyToFadeOut()) {
|
||||
@@ -33,8 +33,8 @@
|
||||
try {
|
||||
this.reload.checkExceptions();
|
||||
this.onFinish.accept(Optional.empty());
|
||||
@@ -134,7 +_,6 @@
|
||||
this.onFinish.accept(Optional.of(throwable));
|
||||
@@ -164,7 +_,6 @@
|
||||
this.onFinish.accept(Optional.of(var2));
|
||||
}
|
||||
|
||||
- this.fadeOutStart = Util.getMillis();
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
+ }
|
||||
+
|
||||
+ public static <T extends AbstractContainerMenu> java.util.Optional<ScreenConstructor<T, ?>> getScreenFactory(@Nullable MenuType<T> type, Minecraft minecraft, int containerId, Component title) {
|
||||
MenuScreens.ScreenConstructor<T, ?> screenconstructor = getConstructor(type);
|
||||
if (screenconstructor == null) {
|
||||
MenuScreens.ScreenConstructor<T, ?> constructor = getConstructor(type);
|
||||
if (constructor == null) {
|
||||
LOGGER.warn("Failed to create screen for menu type: {}", BuiltInRegistries.MENU.getKey(type));
|
||||
+ return java.util.Optional.empty();
|
||||
} else {
|
||||
- screenconstructor.fromPacket(title, type, minecraft, containerId);
|
||||
+ return java.util.Optional.of(screenconstructor);
|
||||
- constructor.fromPacket(title, type, minecraft, containerId);
|
||||
+ return java.util.Optional.of(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -104,6 +_,7 @@
|
||||
@@ -102,6 +_,7 @@
|
||||
} else {
|
||||
gridlayout$rowhelper.addChild(this.openScreenButton(PLAYER_REPORTING, () -> new SocialInteractionsScreen(this)));
|
||||
helper.addChild(this.openScreenButton(PLAYER_REPORTING, () -> new SocialInteractionsScreen(this)));
|
||||
}
|
||||
+ gridlayout$rowhelper.addChild(Button.builder(Component.translatable("fml.menu.mods"), button -> this.minecraft.setScreen(new net.minecraftforge.client.gui.ModListScreen(this))).width(BUTTON_WIDTH_FULL).build(), 2);
|
||||
+ helper.addChild(Button.builder(Component.translatable("fml.menu.mods"), button -> this.minecraft.setScreen(new net.minecraftforge.client.gui.ModListScreen(this))).width(BUTTON_WIDTH_FULL).build(), 2);
|
||||
|
||||
this.disconnectButton = gridlayout$rowhelper.addChild(
|
||||
this.disconnectButton = helper.addChild(
|
||||
Button.builder(
|
||||
@@ -9,47 +9,47 @@
|
||||
public TitleScreen() {
|
||||
this(false);
|
||||
@@ -105,11 +_,15 @@
|
||||
int j = this.width - i - 2;
|
||||
int k = 24;
|
||||
int l = this.height / 4 + 48;
|
||||
int copyrightX = this.width - copyrightWidth - 2;
|
||||
int spacing = 24;
|
||||
int topPos = this.height / 4 + 48;
|
||||
+ Button modButton = null;
|
||||
if (this.minecraft.isDemo()) {
|
||||
l = this.createDemoMenuOptions(l, 24);
|
||||
topPos = this.createDemoMenuOptions(topPos, 24);
|
||||
} else {
|
||||
l = this.createNormalMenuOptions(l, 24);
|
||||
topPos = this.createNormalMenuOptions(topPos, 24);
|
||||
+ modButton = this.addRenderableWidget(Button.builder(Component.translatable("fml.menu.mods"), button -> this.minecraft.setScreen(new net.minecraftforge.client.gui.ModListScreen(this)))
|
||||
+ .pos(this.width / 2 - 100, l).size(98, 20).build());
|
||||
+ .pos(this.width / 2 - 100, topPos).size(98, 20).build());
|
||||
}
|
||||
+ modUpdateNotification = net.minecraftforge.client.gui.TitleScreenModUpdateIndicator.init(this, modButton);
|
||||
|
||||
l = this.createTestWorldButton(l, 24);
|
||||
SpriteIconButton spriteiconbutton = this.addRenderableWidget(
|
||||
@@ -176,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, i = topPos + spacing, 200, 20).tooltip(tooltip).build()).active = flag;
|
||||
topPos = this.createTestWorldButton(topPos, 24);
|
||||
SpriteIconButton language = this.addRenderableWidget(
|
||||
@@ -182,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, var6 = topPos + spacing, 200, 20).tooltip(tooltip).build()).active = multiplayerAllowed;
|
||||
this.addRenderableWidget(
|
||||
Button.builder(Component.translatable("menu.online"), button -> this.minecraft.setScreen(new RealmsMainScreen(this)))
|
||||
- .bounds(this.width / 2 - 100, topPos = i + spacing, 200, 20)
|
||||
+ .bounds(this.width / 2 + 2, topPos = i + spacing, 98, 20)
|
||||
- .bounds(this.width / 2 - 100, topPos = var6 + spacing, 200, 20)
|
||||
+ .bounds(this.width / 2 + 2, topPos = var6 + spacing, 98, 20)
|
||||
.tooltip(tooltip)
|
||||
.build()
|
||||
)
|
||||
@@ -304,9 +_,18 @@
|
||||
s = s + I18n.get("menu.modded");
|
||||
@@ -310,9 +_,18 @@
|
||||
versionString = versionString + I18n.get("menu.modded");
|
||||
}
|
||||
|
||||
- graphics.text(this.font, s, 2, this.height - 10, ARGB.white(f));
|
||||
+ final float f_f = f;
|
||||
- graphics.text(this.font, versionString, 2, this.height - 10, ARGB.white(widgetFade));
|
||||
+ final float widgetFade_f = widgetFade;
|
||||
+ net.minecraftforge.internal.BrandingControl.forEachLine(true, true, (brd, brdline) ->
|
||||
+ graphics.text(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.lineHeight + 1)), ARGB.color(f_f, -1))
|
||||
+ graphics.text(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.lineHeight + 1)), ARGB.color(widgetFade_f, -1))
|
||||
+ );
|
||||
+
|
||||
+ net.minecraftforge.internal.BrandingControl.forEachAboveCopyrightLine((brd, brdline) ->
|
||||
+ graphics.text(this.font, brd, this.width - font.width(brd), this.height - (10 + (brdline + 1) * ( this.font.lineHeight + 1)), ARGB.color(f_f, -1))
|
||||
+ graphics.text(this.font, brd, this.width - font.width(brd), this.height - (10 + (brdline + 1) * ( this.font.lineHeight + 1)), ARGB.color(widgetFade_f, -1))
|
||||
+ );
|
||||
+
|
||||
if (this.realmsNotificationsEnabled() && f >= 1.0F) {
|
||||
if (this.realmsNotificationsEnabled() && widgetFade >= 1.0F) {
|
||||
this.realmsNotificationsScreen.extractRenderState(graphics, mouseX, mouseY, a);
|
||||
+ if (f >= 1.0f) this.modUpdateNotification.extractRenderState(graphics, mouseX, mouseY, a);
|
||||
+ if (widgetFade >= 1.0f) this.modUpdateNotification.extractRenderState(graphics, mouseX, mouseY, a);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -27,11 +27,11 @@
|
||||
@@ -155,8 +_,8 @@
|
||||
return null;
|
||||
} else {
|
||||
for (AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
|
||||
- if (index < advancementtabtype.getMax()) {
|
||||
- return new AdvancementTab(minecraft, screen, advancementtabtype, index, root, optional.get());
|
||||
+ if ((index % AdvancementTabType.MAX_TABS) < advancementtabtype.getMax()) {
|
||||
+ return new AdvancementTab(minecraft, screen, advancementtabtype, index % AdvancementTabType.MAX_TABS, index / AdvancementTabType.MAX_TABS, root, optional.get());
|
||||
for (AdvancementTabType type : AdvancementTabType.values()) {
|
||||
- if (index < type.getMax()) {
|
||||
- return new AdvancementTab(minecraft, screen, type, index, root, display.get());
|
||||
+ if ((index % AdvancementTabType.MAX_TABS) < type.getMax()) {
|
||||
+ return new AdvancementTab(minecraft, screen, type, index % AdvancementTabType.MAX_TABS, index / AdvancementTabType.MAX_TABS, root, display.get());
|
||||
}
|
||||
|
||||
index -= advancementtabtype.getMax();
|
||||
index -= type.getMax();
|
||||
+20
-20
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
@@ -51,6 +_,7 @@
|
||||
@@ -50,6 +_,7 @@
|
||||
private final Map<AdvancementHolder, AdvancementTab> tabs = Maps.newLinkedHashMap();
|
||||
private @Nullable AdvancementTab selectedTab;
|
||||
private boolean isScrolling;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public AdvancementsScreen(final ClientAdvancements advancements) {
|
||||
this(advancements, null);
|
||||
@@ -64,6 +_,19 @@
|
||||
@@ -63,6 +_,19 @@
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
@@ -28,33 +28,33 @@
|
||||
this.layout.addTitleHeader(TITLE, this.font);
|
||||
this.tabs.clear();
|
||||
this.selectedTab = null;
|
||||
@@ -106,7 +_,7 @@
|
||||
int j = (this.height - 140) / 2;
|
||||
@@ -105,7 +_,7 @@
|
||||
int yo = (this.height - 140) / 2;
|
||||
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
- if (advancementtab.isMouseOver(i, j, event.x(), event.y())) {
|
||||
+ if (advancementtab.getPage() == tabPage && advancementtab.isMouseOver(i, j, event.x(), event.y())) {
|
||||
this.advancements.setSelectedTab(advancementtab.getRootNode().holder(), true);
|
||||
for (AdvancementTab tab : this.tabs.values()) {
|
||||
- if (tab.isMouseOver(xo, yo, event.x(), event.y())) {
|
||||
+ if (tab.getPage() == tabPage && tab.isMouseOver(xo, yo, event.x(), event.y())) {
|
||||
this.advancements.setSelectedTab(tab.getRootNode().holder(), true);
|
||||
break;
|
||||
}
|
||||
@@ -197,10 +_,12 @@
|
||||
@@ -196,10 +_,12 @@
|
||||
graphics.blit(RenderPipelines.GUI_TEXTURED, WINDOW_LOCATION, xo, yo, 0.0F, 0.0F, 252, 140, 256, 256);
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
+ if (advancementtab.getPage() == tabPage)
|
||||
advancementtab.extractTab(graphics, xo, yo, mouseX, mouseY, advancementtab == this.selectedTab);
|
||||
for (AdvancementTab tab : this.tabs.values()) {
|
||||
+ if (tab.getPage() == tabPage)
|
||||
tab.extractTab(graphics, xo, yo, mouseX, mouseY, tab == this.selectedTab);
|
||||
}
|
||||
|
||||
for (AdvancementTab advancementtab1 : this.tabs.values()) {
|
||||
+ if (advancementtab1.getPage() == tabPage)
|
||||
advancementtab1.extractIcon(graphics, xo, yo);
|
||||
for (AdvancementTab tab : this.tabs.values()) {
|
||||
+ if (tab.getPage() == tabPage)
|
||||
tab.extractIcon(graphics, xo, yo);
|
||||
}
|
||||
}
|
||||
@@ -219,6 +_,7 @@
|
||||
@@ -218,6 +_,7 @@
|
||||
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
+ if (advancementtab.getPage() == tabPage)
|
||||
if (advancementtab.isMouseOver(xo, yo, mouseX, mouseY)) {
|
||||
graphics.setTooltipForNextFrame(this.font, advancementtab.getTitle(), mouseX, mouseY);
|
||||
for (AdvancementTab tab : this.tabs.values()) {
|
||||
+ if (tab.getPage() == tabPage)
|
||||
if (tab.isMouseOver(xo, yo, mouseX, mouseY)) {
|
||||
graphics.setTooltipForNextFrame(this.font, tab.getTitle(), mouseX, mouseY);
|
||||
}
|
||||
+48
-51
@@ -1,34 +1,31 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
@@ -111,6 +_,7 @@
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
int xo = this.leftPos;
|
||||
int yo = this.topPos;
|
||||
super.extractRenderState(graphics, mouseX, mouseY, a);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderBackground(this, graphics, mouseX, mouseY);
|
||||
graphics.pose().pushMatrix();
|
||||
graphics.pose().translate(i, j);
|
||||
graphics.pose().translate(xo, yo);
|
||||
this.extractLabels(graphics, mouseX, mouseY);
|
||||
@@ -122,6 +_,7 @@
|
||||
if (slot != null && slot != this.hoveredSlot) {
|
||||
this.onStopHovering(slot);
|
||||
if (previouslyHoveredSlot != null && previouslyHoveredSlot != this.hoveredSlot) {
|
||||
this.onStopHovering(previouslyHoveredSlot);
|
||||
}
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderForeground(this, graphics, mouseX, mouseY);
|
||||
|
||||
graphics.pose().popMatrix();
|
||||
}
|
||||
@@ -203,9 +_,9 @@
|
||||
this.font,
|
||||
this.getTooltipFromContainerItem(itemstack),
|
||||
itemstack.getTooltipImage(),
|
||||
+ itemstack,
|
||||
mouseX,
|
||||
- mouseY,
|
||||
- itemstack.get(DataComponents.TOOLTIP_STYLE)
|
||||
+ mouseY
|
||||
@@ -200,7 +_,7 @@
|
||||
ItemStack item = this.hoveredSlot.getItem();
|
||||
if (this.menu.getCarried().isEmpty() || this.showTooltipWithItemInHand(item)) {
|
||||
graphics.setTooltipForNextFrame(
|
||||
- this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), mouseX, mouseY, item.get(DataComponents.TOOLTIP_STYLE)
|
||||
+ this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), item, mouseX, mouseY
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -221,7 +_,8 @@
|
||||
@@ -216,7 +_,8 @@
|
||||
|
||||
private void extractFloatingItem(final GuiGraphicsExtractor graphics, final ItemStack carried, final int x, final int y, final @Nullable String itemCount) {
|
||||
graphics.item(carried, x, y);
|
||||
@@ -38,75 +35,75 @@
|
||||
}
|
||||
|
||||
protected void extractLabels(final GuiGraphicsExtractor graphics, final int xm, final int ym) {
|
||||
@@ -319,7 +_,8 @@
|
||||
@@ -316,7 +_,8 @@
|
||||
if (super.mouseClicked(event, doubleClick)) {
|
||||
return true;
|
||||
} else {
|
||||
- boolean flag = this.minecraft.options.keyPickItem.matchesMouse(event) && this.minecraft.player.hasInfiniteMaterials();
|
||||
- boolean cloning = this.minecraft.options.keyPickItem.matchesMouse(event) && this.minecraft.player.hasInfiniteMaterials();
|
||||
+ var mouseKey = com.mojang.blaze3d.platform.InputConstants.Type.MOUSE.getOrCreate(event.button());
|
||||
+ boolean flag = this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey) && this.minecraft.player.hasInfiniteMaterials();
|
||||
+ boolean cloning = this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey) && this.minecraft.player.hasInfiniteMaterials();
|
||||
Slot slot = this.getHoveredSlot(event.x(), event.y());
|
||||
this.doubleclick = this.lastClickSlot == slot && doubleClick;
|
||||
this.skipNextRelease = false;
|
||||
@@ -329,6 +_,7 @@
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
boolean flag1 = this.hasClickedOutside(event.x(), event.y(), i, j);
|
||||
+ if (slot != null) flag1 = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
int k = -1;
|
||||
@@ -326,6 +_,7 @@
|
||||
int xo = this.leftPos;
|
||||
int yo = this.topPos;
|
||||
boolean clickedOutside = this.hasClickedOutside(event.x(), event.y(), xo, yo);
|
||||
+ if (slot != null) clickedOutside = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
int slotId = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -354,7 +_,7 @@
|
||||
slotId = slot.index;
|
||||
@@ -351,7 +_,7 @@
|
||||
}
|
||||
} else if (!this.isQuickCrafting) {
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
- if (flag) {
|
||||
- if (cloning) {
|
||||
+ if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(slot, k, event.button(), ContainerInput.CLONE);
|
||||
this.slotClicked(slot, slotId, event.button(), ContainerInput.CLONE);
|
||||
} else {
|
||||
boolean flag2 = k != -999 && event.hasShiftDown();
|
||||
@@ -378,7 +_,7 @@
|
||||
boolean quickKey = slotId != -999 && event.hasShiftDown();
|
||||
@@ -375,7 +_,7 @@
|
||||
this.quickCraftingType = 0;
|
||||
} else if (event.button() == 1) {
|
||||
this.quickCraftingType = 1;
|
||||
- } else if (flag) {
|
||||
- } else if (cloning) {
|
||||
+ } else if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.quickCraftingType = 2;
|
||||
}
|
||||
}
|
||||
@@ -448,10 +_,13 @@
|
||||
@@ -445,10 +_,13 @@
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(final MouseButtonEvent event) {
|
||||
+ super.mouseReleased(event); //Forge, Call parent to release buttons
|
||||
Slot slot = this.getHoveredSlot(event.x(), event.y());
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
boolean flag = this.hasClickedOutside(event.x(), event.y(), i, j);
|
||||
+ if (slot != null) flag = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
int xo = this.leftPos;
|
||||
int yo = this.topPos;
|
||||
boolean clickedOutside = this.hasClickedOutside(event.x(), event.y(), xo, yo);
|
||||
+ if (slot != null) clickedOutside = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
+ var mouseKey = com.mojang.blaze3d.platform.InputConstants.Type.MOUSE.getOrCreate(event.button());
|
||||
int k = -1;
|
||||
int slotId = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -468,7 +_,7 @@
|
||||
if (slot1 != null
|
||||
&& slot1.mayPickup(this.minecraft.player)
|
||||
&& slot1.hasItem()
|
||||
- && slot1.container == slot.container
|
||||
+ && slot1.isSameInventory(slot)
|
||||
&& AbstractContainerMenu.canItemQuickReplace(slot1, this.lastQuickMoved, true)) {
|
||||
this.slotClicked(slot1, slot1.index, event.button(), ContainerInput.QUICK_MOVE);
|
||||
slotId = slot.index;
|
||||
@@ -465,7 +_,7 @@
|
||||
if (target != null
|
||||
&& target.mayPickup(this.minecraft.player)
|
||||
&& target.hasItem()
|
||||
- && target.container == slot.container
|
||||
+ && target.isSameInventory(slot)
|
||||
&& AbstractContainerMenu.canItemQuickReplace(target, this.lastQuickMoved, true)) {
|
||||
this.slotClicked(target, target.index, event.button(), ContainerInput.QUICK_MOVE);
|
||||
}
|
||||
@@ -527,7 +_,7 @@
|
||||
@@ -524,7 +_,7 @@
|
||||
} else if (this.isQuickCrafting && !this.quickCraftSlots.isEmpty()) {
|
||||
this.quickCraftToSlots();
|
||||
} else if (!this.menu.getCarried().isEmpty()) {
|
||||
- if (this.minecraft.options.keyPickItem.matchesMouse(event)) {
|
||||
+ if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(slot, k, event.button(), ContainerInput.CLONE);
|
||||
this.slotClicked(slot, slotId, event.button(), ContainerInput.CLONE);
|
||||
} else {
|
||||
boolean flag1 = k != -999 && event.hasShiftDown();
|
||||
@@ -598,7 +_,7 @@
|
||||
boolean quickKey = slotId != -999 && event.hasShiftDown();
|
||||
@@ -595,7 +_,7 @@
|
||||
public boolean keyPressed(final KeyEvent event) {
|
||||
if (super.keyPressed(event)) {
|
||||
return true;
|
||||
@@ -115,7 +112,7 @@
|
||||
this.onClose();
|
||||
return true;
|
||||
} else {
|
||||
@@ -696,6 +_,13 @@
|
||||
@@ -693,6 +_,13 @@
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
+60
-60
@@ -11,7 +11,7 @@
|
||||
super(new CreativeModeInventoryScreen.ItemPickerMenu(player), player.getInventory(), CommonComponents.EMPTY, 195, 136);
|
||||
@@ -164,7 +_,7 @@
|
||||
private void refreshCurrentTabContents(final Collection<ItemStack> displayList) {
|
||||
int i = this.menu.getRowIndexForScroll(this.scrollOffs);
|
||||
int oldRowIndex = this.menu.getRowIndexForScroll(this.scrollOffs);
|
||||
this.menu.items.clear();
|
||||
- if (selectedTab.getType() == CreativeModeTab.Type.SEARCH) {
|
||||
+ if (selectedTab.hasSearchBar()) {
|
||||
@@ -63,7 +63,7 @@
|
||||
+ } else if (!selectedTab.hasSearchBar()) {
|
||||
return false;
|
||||
} else {
|
||||
String s = this.searchBox.getValue();
|
||||
String oldContents = this.searchBox.getValue();
|
||||
@@ -405,7 +_,7 @@
|
||||
@Override
|
||||
public boolean keyPressed(final KeyEvent event) {
|
||||
@@ -80,20 +80,20 @@
|
||||
+ if (!selectedTab.hasSearchBar()) return;
|
||||
this.menu.items.clear();
|
||||
this.visibleTags.clear();
|
||||
String s = this.searchBox.getValue();
|
||||
String searchTerm = this.searchBox.getValue();
|
||||
@@ -453,10 +_,10 @@
|
||||
SearchTree<ItemStack> searchtree;
|
||||
if (s.startsWith("#")) {
|
||||
s = s.substring(1);
|
||||
- searchtree = sessionsearchtrees.creativeTagSearch();
|
||||
+ searchtree = sessionsearchtrees.getSearchTree(net.minecraftforge.client.CreativeModeTabSearchRegistry.getTagSearchKey(selectedTab));
|
||||
this.updateVisibleTags(s);
|
||||
SearchTree<ItemStack> tree;
|
||||
if (searchTerm.startsWith("#")) {
|
||||
searchTerm = searchTerm.substring(1);
|
||||
- tree = searchTrees.creativeTagSearch();
|
||||
+ tree = searchTrees.getSearchTree(net.minecraftforge.client.CreativeModeTabSearchRegistry.getTagSearchKey(selectedTab));
|
||||
this.updateVisibleTags(searchTerm);
|
||||
} else {
|
||||
- searchtree = sessionsearchtrees.creativeNameSearch();
|
||||
+ searchtree = sessionsearchtrees.getSearchTree(net.minecraftforge.client.CreativeModeTabSearchRegistry.getNameSearchKey(selectedTab));
|
||||
- tree = searchTrees.creativeNameSearch();
|
||||
+ tree = searchTrees.getSearchTree(net.minecraftforge.client.CreativeModeTabSearchRegistry.getNameSearchKey(selectedTab));
|
||||
}
|
||||
|
||||
this.menu.items.addAll(searchtree.search(s.toLowerCase(Locale.ROOT)));
|
||||
this.menu.items.addAll(tree.search(searchTerm.toLowerCase(Locale.ROOT)));
|
||||
@@ -484,7 +_,7 @@
|
||||
@Override
|
||||
protected void extractLabels(final GuiGraphicsExtractor graphics, final int xm, final int ym) {
|
||||
@@ -104,22 +104,22 @@
|
||||
}
|
||||
|
||||
@@ -494,7 +_,7 @@
|
||||
double d0 = event.x() - this.leftPos;
|
||||
double d1 = event.y() - this.topPos;
|
||||
double xm = event.x() - this.leftPos;
|
||||
double ym = event.y() - this.topPos;
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
- for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab tab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabClicked(tab, xm, ym)) {
|
||||
return true;
|
||||
}
|
||||
@@ -516,7 +_,7 @@
|
||||
double d1 = event.y() - this.topPos;
|
||||
double ym = event.y() - this.topPos;
|
||||
this.scrolling = false;
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
this.selectTab(creativemodetab);
|
||||
- for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab tab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabClicked(tab, xm, ym)) {
|
||||
this.selectTab(tab);
|
||||
return true;
|
||||
@@ -610,13 +_,15 @@
|
||||
this.originalSlots = null;
|
||||
@@ -130,7 +130,7 @@
|
||||
this.searchBox.setVisible(true);
|
||||
this.searchBox.setCanLoseFocus(false);
|
||||
this.searchBox.setFocused(true);
|
||||
if (creativemodetab != tab) {
|
||||
if (oldTab != tab) {
|
||||
this.searchBox.setValue("");
|
||||
}
|
||||
+ this.searchBox.setWidth(selectedTab.getSearchBarWidth());
|
||||
@@ -142,7 +142,7 @@
|
||||
this.effects.extractRenderState(graphics, mouseX, mouseY);
|
||||
super.extractRenderState(graphics, mouseX, mouseY, a);
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
- for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
|
||||
+ if (this.pages.size() != 1) {
|
||||
+ Component page = Component.literal(String.format("%d / %d", this.pages.indexOf(this.currentPage) + 1, this.pages.size()));
|
||||
+ graphics.pose().pushMatrix();
|
||||
@@ -150,39 +150,39 @@
|
||||
+ graphics.pose().popMatrix();
|
||||
+ }
|
||||
+
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabHovering(graphics, creativemodetab, mouseX, mouseY)) {
|
||||
+ for (CreativeModeTab tab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabHovering(graphics, tab, mouseX, mouseY)) {
|
||||
break;
|
||||
}
|
||||
@@ -701,7 +_,7 @@
|
||||
public List<Component> getTooltipFromContainerItem(final ItemStack itemStack) {
|
||||
boolean flag = this.hoveredSlot != null && this.hoveredSlot instanceof CreativeModeInventoryScreen.CustomCreativeSlot;
|
||||
boolean flag1 = selectedTab.getType() == CreativeModeTab.Type.CATEGORY;
|
||||
- boolean flag2 = selectedTab.getType() == CreativeModeTab.Type.SEARCH;
|
||||
+ boolean flag2 = selectedTab.hasSearchBar();
|
||||
TooltipFlag.Default tooltipflag$default = this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL;
|
||||
TooltipFlag tooltipflag = flag ? tooltipflag$default.asCreative() : tooltipflag$default;
|
||||
List<Component> list = itemStack.getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player, tooltipflag);
|
||||
boolean isCreativeSlot = this.hoveredSlot != null && this.hoveredSlot instanceof CreativeModeInventoryScreen.CustomCreativeSlot;
|
||||
boolean isSingleCategoryTab = selectedTab.getType() == CreativeModeTab.Type.CATEGORY;
|
||||
- boolean isSearchTab = selectedTab.getType() == CreativeModeTab.Type.SEARCH;
|
||||
+ boolean isSearchTab = selectedTab.hasSearchBar();
|
||||
TooltipFlag.Default originalTooltipStyle = this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL;
|
||||
TooltipFlag tooltipStyle = isCreativeSlot ? originalTooltipStyle.asCreative() : originalTooltipStyle;
|
||||
List<Component> originalLines = itemStack.getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player, tooltipStyle);
|
||||
@@ -722,7 +_,7 @@
|
||||
int i = 1;
|
||||
|
||||
for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
- if (creativemodetab.getType() != CreativeModeTab.Type.SEARCH && creativemodetab.contains(itemStack)) {
|
||||
+ if (!creativemodetab.hasSearchBar() && creativemodetab.contains(itemStack)) {
|
||||
list1.add(i++, creativemodetab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
|
||||
for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
|
||||
- if (tab.getType() != CreativeModeTab.Type.SEARCH && tab.contains(itemStack)) {
|
||||
+ if (!tab.hasSearchBar() && tab.contains(itemStack)) {
|
||||
linesToDisplay.add(i++, tab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
|
||||
}
|
||||
}
|
||||
@@ -735,7 +_,7 @@
|
||||
public void extractBackground(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final float a) {
|
||||
super.extractBackground(graphics, mouseX, mouseY, a);
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (creativemodetab != selectedTab) {
|
||||
this.extractTabButton(graphics, mouseX, mouseY, creativemodetab);
|
||||
- for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab tab : currentPage.getVisibleTabs()) {
|
||||
if (tab != selectedTab) {
|
||||
this.extractTabButton(graphics, mouseX, mouseY, tab);
|
||||
}
|
||||
@@ -770,6 +_,7 @@
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, identifier, j, k + (int)((i - k - 17) * this.scrollOffs), 12, 15);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, sprite, xscr, yscr + (int)((yscr2 - yscr - 17) * this.scrollOffs), 12, 15);
|
||||
}
|
||||
|
||||
+ if (currentPage.getVisibleTabs().contains(selectedTab)) //Forge: only display tab selection when the selected tab is on the current page
|
||||
@@ -193,39 +193,39 @@
|
||||
}
|
||||
|
||||
private int getTabX(final CreativeModeTab tab) {
|
||||
- int i = tab.column();
|
||||
+ int i = currentPage.getColumn(tab);
|
||||
int j = 27;
|
||||
int k = 27 * i;
|
||||
- int pos = tab.column();
|
||||
+ int pos = currentPage.getColumn(tab);
|
||||
int spacing = 27;
|
||||
int x = 27 * pos;
|
||||
if (tab.isAlignedRight()) {
|
||||
@@ -791,7 +_,7 @@
|
||||
|
||||
private int getTabY(final CreativeModeTab tab) {
|
||||
int i = 0;
|
||||
int y = 0;
|
||||
- if (tab.row() == CreativeModeTab.Row.TOP) {
|
||||
+ if (currentPage.isTop(tab)) {
|
||||
i -= 32;
|
||||
y -= 32;
|
||||
} else {
|
||||
i += this.imageHeight;
|
||||
y += this.imageHeight;
|
||||
@@ -819,8 +_,8 @@
|
||||
|
||||
protected void extractTabButton(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final CreativeModeTab tab) {
|
||||
boolean flag = tab == selectedTab;
|
||||
- boolean flag1 = tab.row() == CreativeModeTab.Row.TOP;
|
||||
- int i = tab.column();
|
||||
+ boolean flag1 = currentPage.isTop(tab);
|
||||
+ int i = currentPage.getColumn(tab);
|
||||
int j = this.leftPos + this.getTabX(tab);
|
||||
int k = this.topPos - (flag1 ? 28 : -(this.imageHeight - 4));
|
||||
Identifier[] aidentifier;
|
||||
boolean selected = tab == selectedTab;
|
||||
- boolean isTop = tab.row() == CreativeModeTab.Row.TOP;
|
||||
- int pos = tab.column();
|
||||
+ boolean isTop = currentPage.isTop(tab);
|
||||
+ int pos = currentPage.getColumn(tab);
|
||||
int x = this.leftPos + this.getTabX(tab);
|
||||
int y = this.topPos - (isTop ? 28 : -(this.imageHeight - 4));
|
||||
Identifier[] sprites;
|
||||
@@ -834,6 +_,7 @@
|
||||
graphics.requestCursor(CursorTypes.POINTING_HAND);
|
||||
}
|
||||
|
||||
+ com.mojang.blaze3d.opengl.GlStateManager._enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, aidentifier[Mth.clamp(i, 0, aidentifier.length)], j, k, 26, 32);
|
||||
int l = j + 13 - 8;
|
||||
int i1 = k + 16 - 8 + (flag1 ? 1 : -1);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, sprites[Mth.clamp(pos, 0, sprites.length)], x, y, 26, 32);
|
||||
int iconX = x + 13 - 8;
|
||||
int iconY = y + 16 - 8 + (isTop ? 1 : -1);
|
||||
@@ -870,6 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
+21
-21
@@ -1,39 +1,39 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
@@ -47,12 +_,16 @@
|
||||
int j = this.screen.width - i;
|
||||
Collection<MobEffectInstance> collection = this.minecraft.player.getActiveEffects();
|
||||
if (!collection.isEmpty() && j >= 32) {
|
||||
- int k = j >= 120 ? j - 7 : 32;
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenEffectSize(this.screen, j, j < 120, i);
|
||||
int availableWidth = this.screen.width - xo;
|
||||
Collection<MobEffectInstance> activeEffects = this.minecraft.player.getActiveEffects();
|
||||
if (!activeEffects.isEmpty() && availableWidth >= 32) {
|
||||
- int maxWidth = availableWidth >= 120 ? availableWidth - 7 : 32;
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenEffectSize(this.screen, availableWidth, availableWidth < 120, xo);
|
||||
+ if (event == null) return;
|
||||
+ int k = !event.isCompact() ? j - 7 : 32;
|
||||
+ i = event.getHorizontalOffset();
|
||||
int l = 33;
|
||||
if (collection.size() > 5) {
|
||||
l = 132 / (collection.size() - 1);
|
||||
+ int maxWidth = !event.isCompact() ? availableWidth - 7 : 32;
|
||||
+ xo = event.getHorizontalOffset();
|
||||
int yStep = 33;
|
||||
if (activeEffects.size() > 5) {
|
||||
yStep = 132 / (activeEffects.size() - 1);
|
||||
}
|
||||
|
||||
+ Iterable<MobEffectInstance> iterable = collection.stream().filter(net.minecraftforge.client.ForgeHooksClient::shouldRenderEffect).sorted().toList();
|
||||
this.extractEffects(graphics, collection, i, l, mouseX, mouseY, k);
|
||||
+ Iterable<MobEffectInstance> iterable = activeEffects.stream().filter(net.minecraftforge.client.ForgeHooksClient::shouldRenderEffect).sorted().toList();
|
||||
this.extractEffects(graphics, activeEffects, xo, yStep, mouseX, mouseY, maxWidth);
|
||||
}
|
||||
}
|
||||
@@ -72,6 +_,11 @@
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : iterable) {
|
||||
boolean flag = mobeffectinstance.isAmbient();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(mobeffectinstance);
|
||||
+ if (renderer.extractInventory(mobeffectinstance, this, graphics, x0, i, 0)) {
|
||||
+ i += yStep;
|
||||
for (MobEffectInstance effect : sortedEffects) {
|
||||
boolean isAmbient = effect.isAmbient();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(effect);
|
||||
+ if (renderer.extractInventory(effect, this, graphics, x0, y0, 0)) {
|
||||
+ y0 += yStep;
|
||||
+ continue;
|
||||
+ }
|
||||
Component component = this.getEffectName(mobeffectinstance);
|
||||
Component component1 = MobEffectUtil.formatDuration(mobeffectinstance, 1.0F, this.minecraft.level.tickRateManager().tickrate());
|
||||
int j = this.extractBackground(graphics, font, component, component1, x0, i, flag, maxWidth);
|
||||
Component effectText = this.getEffectName(effect);
|
||||
Component duration = MobEffectUtil.formatDuration(effect, 1.0F, this.minecraft.level.tickRateManager().tickrate());
|
||||
int textureWidth = this.extractBackground(graphics, font, effectText, duration, x0, y0, isAmbient, maxWidth);
|
||||
@@ -136,5 +_,9 @@
|
||||
}
|
||||
|
||||
return mutablecomponent;
|
||||
return name;
|
||||
+ }
|
||||
+
|
||||
+ public AbstractContainerScreen<?> getScreen() {
|
||||
|
||||
+27
-26
@@ -1,32 +1,33 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
@@ -111,7 +_,7 @@
|
||||
int l1 = 86 - this.font.width(s);
|
||||
FormattedText formattedtext = EnchantmentNames.getInstance().getRandomName(this.font, l1);
|
||||
int i2 = -9937334;
|
||||
- if ((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) {
|
||||
+ if (((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) || this.menu.enchantClue[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, ENCHANTMENT_SLOT_DISABLED_SPRITE, i1, j + 14 + 19 * l, 108, 19);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, DISABLED_LEVEL_SPRITES[l], i1 + 1, j + 15 + 19 * l, 16, 16);
|
||||
graphics.textWithWordWrap(this.font, formattedtext, j1, j + 16 + 19 * l, l1, ARGB.opaque((i2 & 16711422) >> 1), false);
|
||||
@@ -162,13 +_,16 @@
|
||||
int textWidth = 86 - this.font.width(costText);
|
||||
FormattedText message = EnchantmentNames.getInstance().getRandomName(this.font, textWidth);
|
||||
int col = -9937334;
|
||||
- if ((goldCount < i + 1 || this.minecraft.player.experienceLevel < cost) && !this.minecraft.player.hasInfiniteMaterials()) {
|
||||
+ if (((goldCount < i + 1 || this.minecraft.player.experienceLevel < cost) && !this.minecraft.player.hasInfiniteMaterials()) || this.menu.enchantClue[i] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, ENCHANTMENT_SLOT_DISABLED_SPRITE, leftPos, yo + 14 + 19 * i, 108, 19);
|
||||
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, DISABLED_LEVEL_SPRITES[i], leftPos + 1, yo + 15 + 19 * i, 16, 16);
|
||||
graphics.textWithWordWrap(this.font, message, leftPosText, yo + 16 + 19 * i, textWidth, ARGB.opaque((col & 16711422) >> 1), false);
|
||||
@@ -162,14 +_,18 @@
|
||||
.registryAccess()
|
||||
.lookupOrThrow(Registries.ENCHANTMENT)
|
||||
.get(this.menu.enchantClue[j]);
|
||||
- if (!optional.isEmpty()) {
|
||||
.get(this.menu.enchantClue[i]);
|
||||
- if (!enchant.isEmpty()) {
|
||||
+ {
|
||||
int l = this.menu.levelClue[j];
|
||||
int i1 = j + 1;
|
||||
- if (this.isHovering(60, 14 + 19 * j, 108, 17, mouseX, mouseY) && k > 0 && l >= 0) {
|
||||
+ if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)mouseX, (double)mouseY) && l >= 0) {
|
||||
List<Component> list = Lists.newArrayList();
|
||||
- list.add(Component.translatable("container.enchant.clue", Enchantment.getFullname(optional.get(), l)).withStyle(ChatFormatting.WHITE));
|
||||
- if (!flag) {
|
||||
+ list.add(Component.translatable("container.enchant.clue", optional.isEmpty() ? "" : Enchantment.getFullname(optional.get(), l)).withStyle(ChatFormatting.WHITE));
|
||||
+ if (optional.isEmpty()) {
|
||||
+ list.add(Component.literal(""));
|
||||
+ list.add(Component.translatable("forge.container.enchant.limitedEnchantability").withStyle(ChatFormatting.RED));
|
||||
+ } else if (!flag) {
|
||||
list.add(CommonComponents.EMPTY);
|
||||
if (this.minecraft.player.experienceLevel < k) {
|
||||
list.add(Component.translatable("container.enchant.level.requirement", this.menu.costs[j]).withStyle(ChatFormatting.RED));
|
||||
int enchantLevel = this.menu.levelClue[i];
|
||||
int cost = i + 1;
|
||||
- if (this.isHovering(60, 14 + 19 * i, 108, 17, mouseX, mouseY) && minLevel > 0 && enchantLevel >= 0) {
|
||||
+ if (this.isHovering(60, 14 + 19 * i, 108, 17, (double)mouseX, (double)mouseY) && enchantLevel >= 0) {
|
||||
List<Component> texts = Lists.newArrayList();
|
||||
texts.add(
|
||||
- Component.translatable("container.enchant.clue", Enchantment.getFullname(enchant.get(), enchantLevel)).withStyle(ChatFormatting.WHITE)
|
||||
+ Component.translatable("container.enchant.clue", enchant.isEmpty() ? "" : Enchantment.getFullname(enchant.get(), enchantLevel)).withStyle(ChatFormatting.WHITE)
|
||||
);
|
||||
+ if (enchant.isEmpty()) {
|
||||
+ texts.add(Component.literal(""));
|
||||
+ texts.add(Component.translatable("forge.container.enchant.limitedEnchantability").withStyle(ChatFormatting.RED));
|
||||
+ } else
|
||||
if (!infiniteMaterials) {
|
||||
texts.add(CommonComponents.EMPTY);
|
||||
if (this.minecraft.player.experienceLevel < minLevel) {
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
|
||||
@@ -20,7 +_,7 @@
|
||||
case ClientActivePlayersTooltip.ActivePlayersTooltip clientactiveplayerstooltip$activeplayerstooltip -> new ClientActivePlayersTooltip(
|
||||
clientactiveplayerstooltip$activeplayerstooltip
|
||||
);
|
||||
@@ -18,7 +_,7 @@
|
||||
return (ClientTooltipComponent)(switch (component) {
|
||||
case BundleTooltip bundleTooltip -> new ClientBundleTooltip(bundleTooltip.contents());
|
||||
case ClientActivePlayersTooltip.ActivePlayersTooltip activePlayersTooltip -> new ClientActivePlayersTooltip(activePlayersTooltip);
|
||||
- default -> throw new IllegalArgumentException("Unknown TooltipComponent");
|
||||
+ default -> net.minecraftforge.client.gui.ClientTooltipComponentManager.createClientTooltipComponent(component);
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
@@ -371,6 +_,8 @@
|
||||
@@ -372,6 +_,8 @@
|
||||
graphics.setTooltipForNextFrame(Lists.transform(this.onlinePlayersTooltip, Component::getVisualOrderText), mouseX, mouseY);
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
+
|
||||
if (this.minecraft.options.touchscreen().get() || hovered) {
|
||||
graphics.fill(this.getContentX(), this.getContentY(), this.getContentX() + 32, this.getContentY() + 32, -1601138544);
|
||||
int i1 = mouseX - this.getContentX();
|
||||
int relX = mouseX - this.getContentX();
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
+++ b/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
@@ -123,9 +_,10 @@
|
||||
@@ -122,9 +_,10 @@
|
||||
this.name = name;
|
||||
this.changeButton = Button.builder(name, button -> {
|
||||
KeyBindsList.this.keyBindsScreen.selectedKey = key;
|
||||
@@ -12,7 +12,7 @@
|
||||
.createNarration(
|
||||
defaultNarrationSupplier -> key.isUnbound()
|
||||
? Component.translatable("narrator.controls.unbound", name)
|
||||
@@ -133,7 +_,7 @@
|
||||
@@ -132,7 +_,7 @@
|
||||
)
|
||||
.build();
|
||||
this.resetButton = Button.builder(RESET_BUTTON_TITLE, button -> {
|
||||
@@ -21,13 +21,13 @@
|
||||
KeyBindsList.this.resetMappingAndUpdateButtons();
|
||||
}).bounds(0, 0, 50, 20).createNarration(defaultNarrationSupplier -> Component.translatable("narrator.controls.reset", name)).build();
|
||||
this.refreshEntry();
|
||||
@@ -174,7 +_,8 @@
|
||||
MutableComponent mutablecomponent = Component.empty();
|
||||
@@ -173,7 +_,8 @@
|
||||
MutableComponent tooltip = Component.empty();
|
||||
if (!this.key.isUnbound()) {
|
||||
for (KeyMapping keymapping : KeyBindsList.this.minecraft.options.keyMappings) {
|
||||
- if (keymapping != this.key && this.key.same(keymapping) && (!keymapping.isDefault() || !this.key.isDefault())) {
|
||||
+ var vanillConflict = keymapping != this.key && this.key.same(keymapping) && (!keymapping.isDefault() || !this.key.isDefault());
|
||||
+ if (vanillConflict || keymapping.hasKeyModifierConflict(this.key)) { // FORGE: gracefully handle conflicts like SHIFT vs SHIFT+G
|
||||
for (KeyMapping otherKey : KeyBindsList.this.minecraft.options.keyMappings) {
|
||||
- if (otherKey != this.key && this.key.same(otherKey) && (!otherKey.isDefault() || !this.key.isDefault())) {
|
||||
+ var vanillConflict = otherKey != this.key && this.key.same(otherKey) && (!otherKey.isDefault() || !this.key.isDefault());
|
||||
+ if (vanillConflict || otherKey.hasKeyModifierConflict(this.key)) { // FORGE: gracefully handle conflicts like SHIFT vs SHIFT+G
|
||||
if (this.hasCollision) {
|
||||
mutablecomponent.append(", ");
|
||||
tooltip.append(", ");
|
||||
}
|
||||
+4
-4
@@ -3,9 +3,9 @@
|
||||
@@ -42,7 +_,7 @@
|
||||
protected void addFooter() {
|
||||
this.resetButton = Button.builder(Component.translatable("controls.resetAll"), button -> {
|
||||
for (KeyMapping keymapping : this.options.keyMappings) {
|
||||
- keymapping.setKey(keymapping.getDefaultKey());
|
||||
+ keymapping.setToDefault();
|
||||
for (KeyMapping key : this.options.keyMappings) {
|
||||
- key.setKey(key.getDefaultKey());
|
||||
+ key.setToDefault();
|
||||
}
|
||||
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -27,7 +27,7 @@
|
||||
@@ -101,5 +_,18 @@
|
||||
}
|
||||
|
||||
this.resetButton.active = flag;
|
||||
this.resetButton.active = canReset;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/client/gui/screens/packs/TransferableSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/packs/TransferableSelectionList.java
|
||||
@@ -66,7 +_,7 @@
|
||||
Component component = Component.empty().append(this.title).withStyle(ChatFormatting.UNDERLINE, ChatFormatting.BOLD);
|
||||
this.addEntry(new TransferableSelectionList.HeaderEntry(this.minecraft.font, component), (int)(9.0F * 1.5F));
|
||||
Component header = Component.empty().append(this.title).withStyle(ChatFormatting.UNDERLINE, ChatFormatting.BOLD);
|
||||
this.addEntry(new TransferableSelectionList.HeaderEntry(this.minecraft.font, header), (int)(9.0F * 1.5F));
|
||||
this.setSelected(null);
|
||||
- entries.forEach(e -> {
|
||||
+ entries.filter(PackSelectionModel.Entry::notHidden).forEach(e -> {
|
||||
TransferableSelectionList.PackEntry transferableselectionlist$packentry = new TransferableSelectionList.PackEntry(this.minecraft, this, e);
|
||||
this.addEntry(transferableselectionlist$packentry);
|
||||
TransferableSelectionList.PackEntry entry = new TransferableSelectionList.PackEntry(this.minecraft, this, e);
|
||||
this.addEntry(entry);
|
||||
if (transferredEntry != null && transferredEntry.getId().equals(e.getId())) {
|
||||
+10
-10
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
|
||||
@@ -177,6 +_,7 @@
|
||||
WorldDataConfiguration worlddataconfiguration = SharedConstants.IS_RUNNING_IN_IDE
|
||||
@@ -174,6 +_,7 @@
|
||||
WorldDataConfiguration dataConfig = SharedConstants.IS_RUNNING_IN_IDE
|
||||
? new WorldDataConfiguration(new DataPackConfig(List.of("vanilla", "tests"), List.of()), FeatureFlags.DEFAULT_FLAGS)
|
||||
: WorldDataConfiguration.DEFAULT;
|
||||
+ net.minecraftforge.event.ForgeEventFactory.addPackFindersServer(packrepository::addPackFinder);
|
||||
WorldLoader.InitConfig worldloader$initconfig = createDefaultLoadConfig(packrepository, worlddataconfiguration);
|
||||
CompletableFuture<WorldCreationContext> completablefuture = WorldLoader.load(
|
||||
worldloader$initconfig,
|
||||
@@ -520,7 +_,7 @@
|
||||
+ net.minecraftforge.event.ForgeEventFactory.addPackFindersServer(vanillaOnlyPackRepository::addPackFinder);
|
||||
WorldLoader.InitConfig loadConfig = createDefaultLoadConfig(vanillaOnlyPackRepository, dataConfig);
|
||||
CompletableFuture<WorldCreationContext> loadResult = WorldLoader.load(
|
||||
loadConfig,
|
||||
@@ -509,7 +_,7 @@
|
||||
if (retry) {
|
||||
onAbort.accept(this.uiState.getSettings().dataConfiguration());
|
||||
} else {
|
||||
@@ -17,10 +17,10 @@
|
||||
}
|
||||
},
|
||||
Component.translatable("dataPack.validation.failed"),
|
||||
@@ -634,6 +_,7 @@
|
||||
if (path != null) {
|
||||
@@ -623,6 +_,7 @@
|
||||
if (dataPackDir != null) {
|
||||
if (this.tempDataPackRepository == null) {
|
||||
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
|
||||
this.tempDataPackRepository = ServerPacksSource.createPackRepository(dataPackDir, this.packValidator);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(this.tempDataPackRepository, false);
|
||||
this.tempDataPackRepository.reload();
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/PresetEditor.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/PresetEditor.java
|
||||
@@ -29,6 +_,10 @@
|
||||
@@ -28,6 +_,10 @@
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public interface PresetEditor {
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
|
||||
@@ -234,7 +_,7 @@
|
||||
@@ -229,7 +_,7 @@
|
||||
|
||||
public @Nullable PresetEditor getPresetEditor() {
|
||||
Holder<WorldPreset> holder = this.getWorldType().preset();
|
||||
- return holder != null ? PresetEditor.EDITORS.get(holder.unwrapKey()) : null;
|
||||
+ return holder != null ? holder.unwrapKey().map(net.minecraftforge.client.PresetEditorManager::get).orElse(null) : null; // FORGE: redirect lookup to expanded map
|
||||
Holder<WorldPreset> preset = this.getWorldType().preset();
|
||||
- return preset != null ? PresetEditor.EDITORS.get(preset.unwrapKey()) : null;
|
||||
+ return preset != null ? preset.unwrapKey().map(net.minecraftforge.client.PresetEditorManager::get).orElse(null) : null; // FORGE: redirect lookup to expanded map
|
||||
}
|
||||
|
||||
public List<WorldCreationUiState.WorldTypeEntry> getNormalPresetList() {
|
||||
Loaded 100 of 526 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user