Compare commits

..
78 Commits
Author SHA1 Message Date
Jonathing 753d68d20b 1.20.1 RB 4
https://forums.minecraftforge.net/topic/154387-forge-474-minecraft-1201/
2025-03-04 17:36:12 -05:00
Jonathing 4cd832fc4d Fix ForgeDev's test runs not working due to dead test mod (#10483) 2025-03-04 13:53:12 -08:00
Jonathing 8f074e1da1 Cache this.useItem before running item break logic, Fixes #10344 (#10376) 2025-03-04 13:30:10 -08:00
JonathingandLexManos 1596190810 Speed up mod annotation scanning by ~30% (#10470)
Co-authored-by: LexManos <[email protected]>
2025-03-04 13:26:07 -08:00
Jonathing 1fa795a103 Add missed license headers (#10479) 2025-03-04 13:25:58 -08:00
Jonathing fcbd3593f6 Add '#forge:chorus_additionally_grows_on' tag for similar mechanics to '#minecraft:azalea_grows_on' but for chorus (#10456) 2025-03-04 13:25:47 -08:00
Jonathing 68a8d3b830 Fix cancelling ProjectileImpactEvent still firing onBlockHit (#10481) 2025-03-04 12:11:11 -08:00
Jonathing 783c8b7d2b Honor attacker shield disabling status (#10321) 2025-02-18 14:58:43 -08:00
Jonathing dd2591b5f3 Add fast graphics render type to block model jsons (#10393)
Make modded leaves behave like vanilla leaves by default (Fixes #10389)
2025-02-18 13:40:12 -08:00
Jonathing 4cf787d7dd Fix invalidly symlinked worlds crashing on level select (#10439) 2025-02-18 13:14:12 -08:00
Jonathing b805fa74f8 Backport even more future ResourceLocation methods (#10428) 2025-02-18 13:13:58 -08:00
Jonathing fa109380f7 Ensure NetworkConstants is loaded before mod construction (#10407) 2025-02-06 10:49:59 -08:00
Jonathing 59979642e9 Account for problematic mixins in VillagerTrades.EmeraldsForVillagerTypeItem (#10402) 2025-02-05 09:04:56 -08:00
Jonathing 90e8fb1c33 Fix incorrect method reference in TntBlock.explode() 2025-01-27 20:20:30 -08:00
Joseph T. McQuigg f09c6d0a8e Fix issues in VillagerTrades.EmeraldsForVillagerTypeItem related to custom Villager Types (#10315)
Add VillagerType#registerBiomeType
Signed-off-by: Joseph T. McQuigg <[email protected]>
2025-01-27 20:20:08 -08:00
Paint_NinjaandJonathing 56eb44f1cb Add clientSideOnly feature to mods.toml (#10085) (backport of #9804 to 1.20.1)
Co-authored-by: Jonathing <[email protected]>
2025-01-23 20:30:03 +00:00
Jonathing 2e7e537029 Fix non-passengers being tickable without checking canUpdate() (#10304) 2025-01-22 13:36:57 -08:00
Jonathing b9600a27dc Fix finalizeSpawn's return value not being used correctly (#10301) 2025-01-22 13:36:49 -08:00
Jonathing d736300566 Bump CoreMods to 5.2.4 (#10263) 2024-12-23 19:34:27 -08:00
Jonathing fea0d014b8 Allow mipmap lowering to be disabled (#10252) 2024-12-23 19:34:19 -08:00
Jonathing ea355d9bb6 Add optional fix of use item duration, disabled by default (#10246) 2024-12-23 19:15:03 -08:00
JonathingandPaint_Ninja a5293855d6 Backport some Vanilla 1.21 ResourceLocation methods (#10241)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 18:57:33 -08:00
JonathingandPaint_Ninja 4ab4dacf6c Simplify memory usage display on loading screen (#10233)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 18:57:04 -08:00
JonathingandPaint_Ninja 442f4723c8 Deprecate @ObjectHolder, add a couple of fast-paths (#10228)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 18:56:46 -08:00
JonathingandPaint_Ninja 12682da09a Skip Vanilla classes for the CapabilityTokenSubclass transformer (#10221)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 18:39:58 -08:00
JonathingandPaint_Ninja da4112efa9 Skip Forge classes in the RuntimeEnumExtender transformer (#10216)
Mod classes are still transformed as usual

Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 18:06:02 -08:00
JonathingandPaint_Ninja ca6094c73d Skip processing Forge classes in RuntimeDistCleaner (#10208)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 17:49:22 -08:00
Jonathing 9f4d3ef1d7 Disable clean on TeamCity (#10258) 2024-12-23 17:30:33 -08:00
Jonathing 622e560b21 Bump CoreMods to 5.2 (#10130)
Full Changelog:
https://gist.github.com/Jonathing/c3ad28b2a048ac839a7baba5417ee870

The key features are:
- ES6 language support
- Thoroughly updated ASMAPI, with full documentation
- Bug fixes (some optional for backwards-compatibility)
- Partial internal code cleanup
- Request CoreMods to not apply fix for ASMAPI.findFirstInstructionBefore by default
- Updated ASM to 9.7.1
- Updated Nashorn to 15.4
2024-11-08 17:58:50 -08:00
Paint_Ninjaandandan42 f7e5db7149 Remove unneeded boat patch (backport of #10061 to 1.20.1) (#10096)
Co-authored-by: andan42 <[email protected]>
2024-10-06 18:52:29 -07:00
Paint_NinjaandRealMangoRage 29986615fe Optionally supply FMLJavaModLoadingContext as a param to mod constructors (backport of #10074 to 1.20.1) (#10100)
Co-authored-by: RealMangoRage <[email protected]>
2024-09-12 14:06:42 +01:00
Paint_Ninja e615774a0e Minor cleanup to ModListScreen and VersionChecker (backport of #9988 to 1.20.1) (#10095) 2024-09-12 14:06:20 +01:00
Paint_Ninja 9779f8eaad Cleanup FML Bindings (backport of #10004 to 1.20.1) (#10094) 2024-09-12 14:06:08 +01:00
Paint_Ninja e643bbb764 Early display fixes/workarounds for buggy drivers. Backport of #9921 to 1.20.1 (#10073) 2024-08-20 13:07:49 -07:00
James Mitchell 25bc8679b5 Add a way to render tooltips from Formatted text and TooltipComponents elements (#10055)
Backport of #10056 for 1.20.1
2024-08-16 22:51:00 +01:00
Thomas Kern 361e99805e Make HangingSignBlockEntity useable with custom BlockEntityTypes. #10038 2024-07-05 14:22:36 -07:00
Edouard127andLexManos 0d3921efb5 Unlock wrapped registries when firing register events. (#10035)
Co-authored-by: LexManos <[email protected]>
2024-07-02 11:09:00 -07:00
Jonathingandthedarkcolour 7eee9dcbcd Choose default JarJar mod file type based on parent JAR (#10023)
Co-authored-by: thedarkcolour <[email protected]>
2024-06-28 22:55:31 -07:00
JonathingandVen 3098f463a0 Fixed falling block entities not rendering as moving blocks (#10006) (#10018)
Co-authored-by: Ven <[email protected]>
2024-06-28 22:36:07 -07:00
LexManos 862d557279 Fix boat travel distance being incorrect. Closes #9997 #9999 2024-06-04 10:35:59 -07:00
LexManos e1f057278d 1.20.1 RB 3
https://forums.minecraftforge.net/topic/139825-forge-473-minecraft-1201/
2024-06-03 13:36:29 -07:00
LexManos 6bbe2c64a9 Bump gradle to 8.8 2024-06-03 13:17:20 -07:00
LexManos 684cd96e32 Bump gradle and java runtime version on team city 2024-06-03 13:00:13 -07:00
LexManos 1f4e13fce0 Fix LevelSettings ignoring data configuration. Close #9938 2024-06-03 12:50:43 -07:00
LexManos 55ad9e6d7d Fix erroneous patch in FireBlock. Closes #9996 2024-06-03 12:50:30 -07:00
Paint_Ninja 5c8d1618bc Fix early window crash when parsing options.txt (#9934)
Backport of #9933
2024-05-09 23:16:13 +01:00
Paint_Ninja a6f5057840 Prevent mixins from crashing the game when there are missing mods (#9916)
1.20.1 backport of 49.0.14
2024-05-08 22:06:39 +01:00
Paint_NinjaandJ-RAP 1b0360928f Fix NPE when acceptableValues in defineInList() does not allow nulls, backport of #9903 (#9907)
Co-authored-by: J-RAP <[email protected]>
2024-04-18 21:22:11 +01:00
Paint_Ninja 921771bd11 Fix Crowdin (#9929) 2024-04-18 21:05:13 +01:00
Paint_Ninja 089bb1fc84 Optimise capabilities a tad, backport of #9886 (#9911) 2024-04-18 20:33:15 +01:00
Paint_Ninja 602f1ef947 Add helper method to OnDatapackSyncEvent, backport of #9901 (#9919) 2024-04-18 20:32:29 +01:00
Paint_Ninja 3b18e003f6 Add CPU usage config option to early window, hide by default, backport of #9866 (#9915) 2024-04-18 20:32:05 +01:00
Paint_NinjaandDennis C c33f2d1be6 Fix slightly offset mods screen link positioning, backport of #9860 (#9861)
Co-authored-by: Dennis C <[email protected]>
2024-04-18 20:31:40 +01:00
Paint_Ninja 022116141c Make common config screen registration tasks easier, backport of #9884 (#9912) 2024-04-18 20:31:01 +01:00
Joseph T. McQuigg a8b243c0cd Add Leaves method to ModelProvider.java (#9889) 2024-04-04 13:54:13 +01:00
Paint_Ninja c22355cc45 [1.20.1] Bump CoreMods and ASM (#9897)
- CoreMods 5.1.2 -> 5.1.6
- ASM 9.6 -> 9.7
2024-04-04 13:52:49 +01:00
J-RAP 74bc36307e Bump some deps (#9880)
- CoreMods 5.0.1 -> 5.1.2
- ASM 9.5 -> 9.6
- Installer 2.1 -> 2.2
- Installer tools 1.3.0 -> 1.4.1
2024-03-10 21:22:53 +00:00
LexManos 88d2dc6c8f Fix missing patch for Item.onInventoryTick. Closes #9812 2024-01-13 12:38:56 -08:00
Paint_Ninja de13ba8ab8 Make common DisplayTest registration tasks easier (#9823) 2023-12-27 09:13:37 -08:00
Paint_Ninja 4f838a87d4 Optimise ForgeConfigSpec and make Range public (#9824)
Backport of #9810 to 1.20.1
2023-12-19 13:24:07 -08:00
J.T. McQuigg 70d700e630 Datagen addOptionalTag/s methods that allow passing the TagKey itself instead of passing the location (#9807) (#9808) 2023-12-04 22:25:14 -08:00
Paint_Ninja 78fffcf45a Update VersionSupportMatrix.java (#9805) 2023-11-29 11:12:12 -08:00
J-RAP cdba403ab6 Backport of Registries optimization, now uses fastutils collections to minimize boxing 2023-11-29 11:11:55 -08:00
LexManos 6821d7b1cc Fix patch offset 2023-11-28 21:19:54 -08:00
LexManos 9524ce4580 Fix fire related mobs not taking enough freezing damage. Closes #9686 2023-11-28 20:10:28 -08:00
LexManos f2bbeab3b9 Fix TagLoader error not printing tag name correctly. Closes #9693 2023-11-28 20:09:47 -08:00
LexManos 4a8adf5465 Fix LoadingErrorScreen inner headers are not centered. Closes #9687 2023-11-28 20:08:59 -08:00
LexManos f5fa2f2a57 Rework KeyModifiers system to properly allow keybinds to be triggered when multiple modifiers are pressed.
Fix setting keybinds whel using keyboard inputs to select the menu. Closes #9793
2023-11-28 20:07:44 -08:00
LexManos b33e168969 Fix KeyModifiers not being properly taken into account. Closes #9806 2023-11-28 19:56:02 -08:00
Paint_Ninjaandembeddedt 1f6e1ff257 Don't turn off VSync when rendering from Minecraft context (#9801)
Co-authored-by: embeddedt <[email protected]>
2023-11-26 16:57:11 -08:00
Paint_Ninja 7f8897141e Fix rare crash with early display window, fixes MinecraftForge#9673 (#9799) 2023-11-26 16:24:45 -08:00
LexManos b9a097c9e1 Fix tag loading being unordered. Closes #9774 2023-11-13 08:50:07 -08:00
LexManos 62f00266c5 Fix misaligned patch in RegistryDataLoader 2023-11-10 11:26:16 -08:00
Paint_Ninja 6986cd7ab3 Backport CrashReportAnalyser to 1.20.1 (#9757) 2023-11-02 12:45:49 -07:00
Paint_Ninja e7051b3484 Minor MDK changes (#9752) 2023-11-02 12:45:39 -07:00
Paint_NinjaandSu5eD f667d25d0b Improve mod description formatting in mods screen (#9769)
Co-authored-by: Su5eD <[email protected]>
2023-11-02 12:45:29 -07:00
Paint_Ninja 48d72fb7c6 [1.20.1] Improve mod loading error message for errors inside mod constructors (#9707) 2023-09-28 00:20:40 -07:00
LexManos 2fb2bbeed0 1.20.1 RB 2023-09-21 10:17:41 -07:00
470 changed files with 8697 additions and 4676 deletions

No files matched your search

+1
View File
@@ -23,6 +23,7 @@
/projects/mcp/
/projects/clean/
/projects/forge/
/projects/fmlonly/
#/patches/*
#occupational hazards
+2 -2
View File
@@ -36,8 +36,8 @@ project {
buildType(PullRequestCompatibility)
params {
text("docker_jdk_version", "17", label = "Gradle version", description = "The version of the JDK to use during execution of tasks in a JDK.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("docker_gradle_version", "7.5.1", label = "Gradle version", description = "The version of Gradle to use during execution of Gradle tasks.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("docker_jdk_version", "21", label = "Gradle version", description = "The version of the JDK to use during execution of tasks in a JDK.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("docker_gradle_version", "8.8", label = "Gradle version", description = "The version of Gradle to use during execution of Gradle tasks.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("git_main_branch", "1.20.x", label = "Git Main Branch", description = "The git main or default branch to use in VCS operations.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("git_branch_spec", """
+:refs/heads/(main*)
+420 -66
View File
@@ -1,3 +1,4 @@
import de.undercouch.gradle.tasks.download.Download
import groovy.json.JsonBuilder
import net.minecraftforge.forge.tasks.checks.CheckATs
import net.minecraftforge.forge.tasks.checks.CheckExcs
@@ -24,8 +25,9 @@ import org.objectweb.asm.Opcodes
plugins {
id 'org.cadixdev.licenser' version '0.6.1'
id 'com.github.ben-manes.versions' version '0.46.0'
id 'net.minecraftforge.gradleutils' version '2.+'
id 'net.minecraftforge.gradleutils' version '[2.2,2.3)'
id 'eclipse'
id 'idea'
id 'de.undercouch.download' version '5.4.0'
id 'net.minecraftforge.gradle.patcher' version '[6.0.11,6.2)' apply false
id 'net.minecraftforge.gradle.mcp' version '[6.0.11,6.2)' apply false
@@ -43,22 +45,22 @@ ext {
]
}
MAPPING_CHANNEL = 'official'
MC_VERSION = '1.20.2-pre1'
MAPPING_VERSION = MC_VERSION
MAPPING_VERSION = '1.20.1'
MC_VERSION = '1.20.1'
MC_NEXT_VERSION = '1.21'
MCP_VERSION = '20230906.154413'
MCP_VERSION = '20230612.114412'
SNAPSHOT = false
SPI_VERSION = '7.0.1'
MERGETOOL_VERSION = '1.1.5'
ACCESSTRANSFORMERS_VERSION = '8.0.4'
COREMODS_VERSION = '5.0.1'
COREMODS_VERSION = '5.2.4'
EVENTBUS_VERSION = '6.0.5'
MODLAUNCHER_VERSION = '10.0.9'
SECUREJARHANDLER_VERSION = '2.1.10'
BOOTSTRAPLAUNCHER_VERSION = '1.1.2'
ASM_VERSION = '9.5'
INSTALLER_VERSION = '2.1.+'
ASM_VERSION = '9.7.1'
INSTALLER_VERSION = '2.2.+'
MIXIN_VERSION = '0.8.5'
TERMINALCONSOLEAPPENDER_VERSION = '1.2.0'
JLINE_VERSION = '3.12.+'
@@ -72,11 +74,11 @@ ext {
// To use a version newer than the version manifest JSON, the dependency must be added to the installer configuration
MOJANG_LOGGING_VERSION = '1.1.1'
LOG4J_VERSION = '2.19.0'
GUAVA_VERSION = '32.1.2-jre'
GSON_VERSION = '2.10.1'
GUAVA_VERSION = '31.1-jre'
GSON_VERSION = '2.10'
APACHE_COMMONS_LANG3_VERSION = '3.12.0'
JOPT_SIMPLE_VERSION = '5.0.4'
COMMONS_IO_VERSION = '2.13.0'
COMMONS_IO_VERSION = '2.11.0'
GIT_INFO = gradleutils.gitInfo
VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION)
@@ -84,9 +86,9 @@ ext {
FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.1.1:fatjar'
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.3.0'
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.1'
JAR_SPLITTER = 'net.minecraftforge:jarsplitter:1.1.4'
FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.5:all'
FART = 'net.minecraftforge:ForgeAutoRenamingTool:0.1.22:all'
MIN_TAG_FOR_CHANGELOG = '41.0'
}
@@ -225,45 +227,47 @@ project(':mcp') {
}
}
project(':clean') {
evaluationDependsOn(':mcp')
apply plugin: 'net.minecraftforge.gradle.patcher'
tasks.withType(AbstractPublishToMaven.class).forEach{tsk -> tsk.enabled = false } // We don't want to publish anything
if (!System.env.TEAMCITY_VERSION) {
project(':clean') {
evaluationDependsOn(':mcp')
apply plugin: 'net.minecraftforge.gradle.patcher'
tasks.withType(AbstractPublishToMaven.class).forEach{tsk -> tsk.enabled = false } // We don't want to publish anything
dependencies {
implementation 'net.minecraftforge:forgespi:' + SPI_VERSION
}
dependencies {
implementation 'net.minecraftforge:forgespi:' + SPI_VERSION
}
patcher {
parent = project(':mcp')
mcVersion = MC_VERSION
patchedSrc = file('src/main/java')
patcher {
parent = project(':mcp')
mcVersion = MC_VERSION
patchedSrc = file('src/main/java')
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
runs {
clean_client {
client true
taskName 'clean_client'
ideaModule "${rootProject.name}.${project.name}.main"
runs {
clean_client {
client true
taskName 'clean_client'
ideaModule "${rootProject.name}.${project.name}.main"
main 'net.minecraft.client.main.Main'
workingDirectory project.file('run')
main 'net.minecraft.client.main.Main'
workingDirectory project.file('run')
args '--gameDir', '.'
args '--version', MC_VERSION
args '--assetsDir', downloadAssets.output
args '--assetIndex', '{asset_index}'
args '--accessToken', '0'
}
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"
clean_server {
client false
taskName 'clean_server'
ideaModule "${rootProject.name}.${project.name}.main"
main 'net.minecraft.server.Main'
workingDirectory project.file('run')
main 'net.minecraft.server.Main'
workingDirectory project.file('run')
}
}
}
}
@@ -301,7 +305,7 @@ def sharedDeps = {
installer "org.jline:jline-reader:${JLINE_VERSION}" // Dep of TerminalConsoleAppender
installer "org.jline:jline-terminal:${JLINE_VERSION}" // Dep of TerminalConsoleAppender
installer "org.spongepowered:mixin:${MIXIN_VERSION}"
installer 'org.openjdk.nashorn:nashorn-core:15.3'
installer 'org.openjdk.nashorn:nashorn-core:15.4'
installer "net.minecraftforge:JarJarSelector:${JARJAR_VERSION}"
installer "net.minecraftforge:JarJarMetadata:${JARJAR_VERSION}"
@@ -354,7 +358,7 @@ def sharedFmlonlyForge = { Project prj ->
}
prj.task([type: DownloadMavenArtifact], 'downloadInstaller') {
artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:shrunk"
artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:fatjar"
changing = true
}
@@ -489,7 +493,7 @@ def sharedFmlonlyForge = { Project prj ->
run.property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll'
run.args '--username', 'Dev'
run.args '--version', prj.name
//run.args '--uuid', '0'
run.args '--uuid', '0'
run.args '--accessToken', '0'
run.args '--userType', 'mojang'
run.args '--versionType', 'release'
@@ -562,8 +566,331 @@ def sharedFmlonlyForge = { Project prj ->
}
}
def symlink = file("$rootDir/fmlonly/src/fmlcommon")
def symlinkValid = symlink.exists() && symlink.directory
if (symlinkValid)
project(':fmlonly') {
evaluationDependsOn(':mcp')
apply plugin: 'java-library'
apply plugin: 'net.minecraftforge.gradle.patcher'
ext {
MCP_ARTIFACT = project(':mcp').mcp.config.get()
PACKED_DEPS = [':fmlcore:jar', ':fmlloader:jar', ':fmlearlydisplay:jar', ':javafmllanguage:jar', ':lowcodelanguage:jar', ':mclanguage:jar']
MAVEN_PATH = "${group.replace('.', '/')}/${project.name}/${VERSION}"
}
sourceSets {
main {
java {
srcDirs = ["$rootDir/fmlonly/src/fmlcommon/java", "$rootDir/fmlonly/src/main/java"]
}
resources {
srcDirs = ["$rootDir/fmlonly/src/fmlcommon/resources", "$rootDir/fmlonly/src/main/resources"]
}
}
}
configurations {
moduleonly
installer {
// Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
transitive = false
}
api.extendsFrom(installer)
}
// TODO: Better coordination between project dependencies and the installer.
dependencies {
implementation project(':fmlcore')
implementation project(':fmlloader')
implementation project(':fmlearlydisplay')
implementation project(':javafmllanguage')
implementation project(':lowcodelanguage')
implementation project(':mclanguage')
runtimeOnly "cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}"
}
dependencies sharedDeps
patcher {
parent = project(':mcp')
mcVersion = MC_VERSION
patchedSrc = file('src/main/java')
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
runs {
fmlonly_client {
args '--launchTarget', 'fmlclientdev'
ideaModule "${rootProject.name}.${project.name}.main"
mods {
minecraft { source sourceSets.main }
}
}
fmlonly_server {
args '--launchTarget', 'fmlserverdev'
ideaModule "${rootProject.name}.${project.name}.main"
mods {
minecraft { source sourceSets.main }
}
}
}
}
sharedFmlonlyForge.call(project)
task launcherJson(type: LauncherJson) {
packedDependencies = [':fmlloader:jar',':fmlearlydisplay:jar']
doFirst {
def fmlonly_client = project(':fmlonly').patcher.runs.fmlonly_client
json = [
_comment_: comment,
id: id,
time: timestamp,
releaseTime: timestamp,
type: 'release',
mainClass: 'cpw.mods.bootstraplauncher.BootstrapLauncher',
inheritsFrom: MC_VERSION,
logging: {},
arguments: [
game: ['--launchTarget', 'fmlclient',
'--fml.forgeVersion', FORGE_VERSION,
'--fml.mcVersion', MC_VERSION,
'--fml.forgeGroup', project.group,
'--fml.mcpVersion', MCP_VERSION],
jvm: ["-DignoreList=${fmlonly_client.properties.ignoreList},\${version_name}.jar",
"-DmergeModules=${fmlonly_client.properties.mergeModules}",
'-DlibraryDirectory=${library_directory}',
'-p', Util.getArtifacts(project, configurations.moduleonly, false).values().collect{"\${library_directory}/${it.downloads.artifact.path}"}.join('${classpath_separator}'),
'--add-modules', 'ALL-MODULE-PATH',
// Additions to these JVM module args should be mirrored to server_files/args.txt and other similar blocks in the buildscript
'--add-opens', 'java.base/java.util.jar=cpw.mods.securejarhandler',
'--add-opens', 'java.base/java.lang.invoke=cpw.mods.securejarhandler',
'--add-exports', 'java.base/sun.security.util=cpw.mods.securejarhandler',
'--add-exports', 'jdk.naming.dns/com.sun.jndi.dns=java.naming'
]
],
libraries: []
]
}
}
task installerJson(type: InstallerJson, dependsOn: 'signUniversalJar') {
icon = rootProject.file('icon.ico')
packedDependencies = PACKED_DEPS
doFirst {
def libs = libraries
json = [
_comment_: launcherJson.comment,
spec: 1,
profile: project.name,
version: launcherJson.id,
path: null,
minecraft: MC_VERSION,
serverJarPath: '{LIBRARY_DIR}/net/minecraft/server/{MINECRAFT_VERSION}/server-{MINECRAFT_VERSION}.jar',
welcome: "Welcome to the simple FML installer.",
data: [
MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]",
server: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]"
],
MOJMAPS: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:mappings@txt]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:mappings@txt]"
],
MERGED_MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings-merged@txt]",
server: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings-merged@txt]"
],
MC_UNPACKED: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:unpacked]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:unpacked]"
],
MC_SLIM: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:slim]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:slim]"
],
MC_SLIM_SHA: [
client: "'${downloadClientSlim.output.get().asFile.sha1()}'",
server: "'${downloadServerSlim.output.get().asFile.sha1()}'"
],
MC_EXTRA: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:extra]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:extra]"
],
MC_EXTRA_SHA: [
client: "'${downloadClientExtra.output.get().asFile.sha1()}'",
server: "'${downloadServerExtra.output.get().asFile.sha1()}'"
],
MC_SRG: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:srg]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:srg]"
],
/*MC_SRG_SHA: [
client: "'${createClientSRG.output.sha1()}'",
server: "'${createServerSRG.output.sha1()}'"
],*/
MCP_VERSION: [
client: "'${MCP_VERSION}'",
server: "'${MCP_VERSION}'"
]
],
processors: [
[
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'EXTRACT_FILES',
'--archive', '{INSTALLER}',
'--from', 'data/run.sh',
'--to', '{ROOT}/run.sh',
'--exec', '{ROOT}/run.sh',
//'--from', "data/run_fml_${VERSION.replace('-', '_').sh",
//'--to', '{ROOT}/run_fml_${VERSION.replace('-', '_').sh',
//'--exec', '{ROOT}/run_fml_${VERSION.replace('-', '_').sh',
'--from', 'data/run.bat',
'--to', '{ROOT}/run.bat',
//'--from', 'data/run_fml_${VERSION.replace('-', '_').bat',
//'--to', '{ROOT}/run_fml_${VERSION.replace('-', '_').bat',
'--from', 'data/user_jvm_args.txt',
'--to', '{ROOT}/user_jvm_args.txt',
'--optional', '{ROOT}/user_jvm_args.txt',
'--from', 'data/win_args.txt',
'--to', "{ROOT}/libraries/${MAVEN_PATH}/win_args.txt",
'--from', 'data/unix_args.txt',
'--to', "{ROOT}/libraries/${MAVEN_PATH}/unix_args.txt"
]
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
'--output', '{ROOT}/libraries/',
'--libraries'
]
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
'--output', '{MC_UNPACKED}',
'--jar-only'
]
], [
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'MCP_DATA',
'--input', "[${MCP_ARTIFACT.descriptor}]",
'--output', '{MAPPINGS}',
'--key', 'mappings'
]
], [
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'DOWNLOAD_MOJMAPS',
'--version', MC_VERSION,
'--side', '{SIDE}',
'--output', '{MOJMAPS}'
]
], [
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'MERGE_MAPPING',
'--left', '{MAPPINGS}',
'--right', '{MOJMAPS}',
'--output', '{MERGED_MAPPINGS}',
'--classes', '--reverse-right'
]
], [
sides: ['client'],
jar: JAR_SPLITTER,
classpath: getClasspath(project, libs, JAR_SPLITTER),
args: [
'--input', '{MINECRAFT_JAR}',
'--slim', '{MC_SLIM}',
'--extra', '{MC_EXTRA}',
'--srg', '{MERGED_MAPPINGS}'
],
outputs: [
'{MC_SLIM}': '{MC_SLIM_SHA}',
'{MC_EXTRA}': '{MC_EXTRA_SHA}'
]
], [
sides: ['server'],
jar: JAR_SPLITTER,
classpath: getClasspath(project, libs, JAR_SPLITTER),
args: [
'--input', '{MC_UNPACKED}',
'--slim', '{MC_SLIM}',
'--extra', '{MC_EXTRA}',
'--srg', '{MERGED_MAPPINGS}'
],
outputs: [
'{MC_SLIM}': '{MC_SLIM_SHA}',
'{MC_EXTRA}': '{MC_EXTRA_SHA}'
]
], [
jar: FART,
classpath: getClasspath(project, libs, FART),
args: [
'--input', '{MC_SLIM}',
'--output', '{MC_SRG}',
'--names', '{MERGED_MAPPINGS}',
'--ann-fix', '--ids-fix', '--src-fix', '--record-fix'
]/*,
outputs: [
'{MC_SRG}': '{MC_SRG_SHA}'
]
*/
]
]
]
getClasspath(project, libs, MCP_ARTIFACT.descriptor) //Tell it to download mcp_config
}
}
task installerJar(type: InstallerJar) {
packedDependencies = PACKED_DEPS
from(extraTxts)
//TODO: make FML installer logo?
from(rootProject.file('/forge_installer_logo.png')) {
rename { 'big_logo.png' }
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact universalJar
artifact installerJar
artifact userdevJar
artifact sourcesJar
}
}
}
// Since we need the modules in the bootstrap, we need to make sure they are compiled before we do each run
afterEvaluate { prepareRuns.dependsOn(PACKED_DEPS) }
}
project(':forge') {
evaluationDependsOn(':clean')
evaluationDependsOn(System.env.TEAMCITY_VERSION ? ':mcp' : ':clean')
apply plugin: 'java-library'
apply plugin: 'net.minecraftforge.gradle.patcher'
apply plugin: 'org.cadixdev.licenser'
@@ -643,13 +970,19 @@ project(':forge') {
patcher {
excs.from file("$rootDir/src/main/resources/forge.exc")
parent = project(':clean')
parent = project(System.env.TEAMCITY_VERSION ? ':mcp' : ':clean')
patches = file("$rootDir/patches/minecraft")
patchedSrc = file('src/main/java')
srgPatches = true
accessTransformers.from file("$rootDir/src/main/resources/META-INF/accesstransformer.cfg")
sideAnnotationStrippers.from file("$rootDir/src/main/resources/forge.sas")
// the clean project provides these. if we're not using it, we need to provide them ourselves
if (System.env.TEAMCITY_VERSION) {
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
mcVersion = MC_VERSION
}
runs {
forge_client {
property 'eventbus.checkTypesOnDispatch', 'true'
@@ -854,9 +1187,12 @@ project(':forge') {
]
}
task crowdin(type: Crowdin) {
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
//TODO: Merge our english.json?
tasks.register('downloadCrowdin', Download) {
src 'https://files.minecraftforge.net/crowdin.zip'
dest file('build/crowdin.zip')
useETag 'all'
onlyIfModified true
quiet true
}
sharedFmlonlyForge.call(project)
@@ -1058,8 +1394,6 @@ project(':forge') {
doFirst {
def libs = libraries
def INSTALLER_TOOLS_CLASSPATH = getClasspath(project, libs, INSTALLER_TOOLS)
def JAR_SPLITTER_CLASSPATH = getClasspath(project, libs, JAR_SPLITTER)
json = [
_comment_: launcherJson.comment,
spec: 1,
@@ -1130,7 +1464,7 @@ project(':forge') {
[
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'EXTRACT_FILES',
'--archive', '{INSTALLER}',
@@ -1160,7 +1494,7 @@ project(':forge') {
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
@@ -1170,7 +1504,7 @@ project(':forge') {
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
@@ -1179,7 +1513,7 @@ project(':forge') {
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'MCP_DATA',
'--input', "[${MCP_ARTIFACT.descriptor}]",
@@ -1188,7 +1522,7 @@ project(':forge') {
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'DOWNLOAD_MOJMAPS',
'--version', MC_VERSION,
@@ -1197,7 +1531,7 @@ project(':forge') {
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'MERGE_MAPPING',
'--left', '{MAPPINGS}',
@@ -1208,7 +1542,7 @@ project(':forge') {
], [
sides: ['client'],
jar: JAR_SPLITTER,
classpath: JAR_SPLITER_CLASSPATH,
classpath: getClasspath(project, libs, JAR_SPLITTER),
args: [
'--input', '{MINECRAFT_JAR}',
'--slim', '{MC_SLIM}',
@@ -1222,7 +1556,7 @@ project(':forge') {
], [
sides: ['server'],
jar: JAR_SPLITTER,
classpath: JAR_SPLITTER_CLASSPATH,
classpath: getClasspath(project, libs, JAR_SPLITTER),
args: [
'--input', '{MC_UNPACKED}',
'--slim', '{MC_SLIM}',
@@ -1269,9 +1603,12 @@ project(':forge') {
from extraTxts
// add crowdin locales
from { crowdin.output.present && crowdin.output.get().asFile.exists() ? zipTree(crowdin.output) : null}
dependsOn crowdin
duplicatesStrategy = 'exclude'
from zipTree(downloadCrowdin.dest).matching {
include 'assets/forge/lang/*.json'
}
dependsOn downloadCrowdin
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
doFirst {
MANIFESTS.each{ pkg, values ->
@@ -1466,7 +1803,10 @@ project(':forge') {
//evaluationDependsOnChildren()
task setup() { //These must be strings so that we can do lazy resolution. Else we need evaluationDependsOnChildren above
dependsOn ':clean:extractMapped'
if (!System.env.TEAMCITY_VERSION)
dependsOn ':clean:extractMapped'
if (symlinkValid)
dependsOn ':fmlonly:extractMapped'
dependsOn ':forge:extractMapped'
}
@@ -1475,14 +1815,28 @@ task doChecks {
dependsOn ':forge:publish'
}
project.gradle.startParameter.excludedTaskNames.add(':clean:genPatches')
if (symlinkValid)
project.gradle.startParameter.excludedTaskNames.add(':fmlonly:genPatches')
if (!System.env.TEAMCITY_VERSION)
project.gradle.startParameter.excludedTaskNames.add(':clean:genPatches')
//Also output FMLOnly when building a version.
if (System.env.TEAMCITY_VERSION) {
//Only setup the CI environment if and only if the environment variables are set.
tasks.configureTeamCity {
doLast {
println "##teamcity[buildNumber '${project(':forge').version}']"
println "##teamcity[setParameter name='env.PUBLISHED_JAVA_ARTIFACT_VERSION' value='${project(':forge').version}']"
println "##teamcity[setParameter name='env.PUBLISHED_JAVA_FML_ARTIFACT_VERSION' value='${project(':fmlonly').version}']"
}
}
}
idea {
module {
// IntelliJ IDEA does not do this by itself anymore...
downloadJavadoc = true
downloadSources = true
}
}
@@ -27,6 +27,6 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
@Internal
@Override
protected Object getData() {
return matches.toSorted(Comparator.naturalOrder()) ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
return matches.stream().sorted().toList() ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
}
}
+30 -11
View File
@@ -2,16 +2,15 @@
MinecraftForge
=============
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.20.1&query=$.promos["1.20.1-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)][Download]
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.20.1-&query=$.promos["1.20.1-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)][Download]
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.20.1-&query=$.promos["1.20.1-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)][Download] [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)][Discord] [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)][Patreon]
Forge is a free, open-source modding API all of your favourite mods use!
| Version | Support |
|---------| ------------- |
| 1.20.x | Active |
| 1.19.x | Legacy |
| Version | Support |
|--------------|-----------------------------|
| All versions | [Supported][Support-Policy] |
* [Download]
* [Forum]
@@ -27,10 +26,23 @@ You can download the installer for the *Recommended Build* or the
*Latest build* there. Latest builds may have newer features but may be
more unstable as a result. The installer will attempt to install Forge
into your vanilla launcher environment, where you can then create a new
profile using that version and play the game!
profile using that version and play the game!
For support and questions, visit [the Support Forum][Support-Forum] or [the Forge Discord server][Discord].
## Required Java Versions
We require the version of Java that Minecraft requires, which is currently:
| Minecraft | Java |
|---------------|-------------------|
| 1.20.6+ | [21][Adoptium-21] |
| 1.18 - 1.20.4 | [17][Adoptium-17] |
| 1.17.1 | [16][Adoptium-16] |
| 1.16.5- | [8][Adoptium-8] |
**If you are on Windows and have difficulty using Java to launch JAR files, consider using [Jarfix by Johann Löfflmann][Jarfix].**
# Creating Mods
[See the "Getting Started" section in the Forge Documentation][Getting-Started].
@@ -63,14 +75,21 @@ Please ensure you have a valid email address associated with your GitHub account
[Download]: https://files.minecraftforge.net/
[Adoptium-21]: https://adoptium.net/temurin/releases/?version=21
[Adoptium-17]: https://adoptium.net/temurin/releases/?version=17
[Adoptium-16]: https://adoptium.net/temurin/releases/?version=16
[Adoptium-8]: https://adoptium.net/temurin/releases/?version=8
[Jarfix]: https://johann.loefflmann.net/en/software/jarfix/index.html
[Forum]: https://forums.minecraftforge.net/
[Support-Forum]: https://forums.minecraftforge.net/forum/18-support-bug-reports/
[Support-Policy]: https://forums.minecraftforge.net/topic/144690-new-tiered-support-policy
[Discord]: https://discord.minecraftforge.net/
[Documentation]: https://docs.minecraftforge.net/
[Getting-Started]: https://docs.minecraftforge.net/en/latest/gettingstarted/
[ForgeDev]: https://docs.minecraftforge.net/en/latest/forgedev/
[Pull-Requests]: https://docs.minecraftforge.net/en/latest/forgedev/#making-changes-and-pull-requests
[Documentation]: https://docs.minecraftforge.net/en/1.20.1/
[Getting-Started]: https://docs.minecraftforge.net/en/1.20.1/gettingstarted/
[ForgeDev]: https://docs.minecraftforge.net/en/1.20.1/forgedev/
[Pull-Requests]: https://docs.minecraftforge.net/en/1.20.1/forgedev/#making-changes-and-pull-requests
[Patreon]: https://www.patreon.com/MinecraftForge
[Patreon]: https://www.patreon.com/LexManos
@@ -5,36 +5,39 @@
package net.minecraftforge.fml;
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.loading.FMLLoader;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.function.Supplier;
/**
* Used to allow access to certain things from the game layer
*/
public class Bindings {
private static final Bindings INSTANCE = new Bindings();
private Bindings() {}
private final IBindingsProvider provider;
private Bindings() {
final var providers = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class), sce->{}).toList();
if (providers.size() != 1) {
throw new IllegalStateException("Could not find bindings provider");
}
this.provider = providers.get(0);
}
/**
* The provider of the bindings
* @implNote May also throw a {@link ServiceConfigurationError}
*/
private static final IBindingsProvider PROVIDER = ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class)
.findFirst().orElseThrow(() -> new IllegalStateException("Could not find bindings provider"));
/**
* @return A supplier of net.minecraftforge.common.MinecraftForge#EVENT_BUS
*/
public static Supplier<IEventBus> getForgeBus() {
return INSTANCE.provider.getForgeBusSupplier();
return PROVIDER.getForgeBusSupplier();
}
public static Supplier<I18NParser> getMessageParser() {
return INSTANCE.provider.getMessageParser();
return PROVIDER.getMessageParser();
}
public static Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration() {
return INSTANCE.provider.getConfigConfiguration();
return PROVIDER.getConfigConfiguration();
}
}
@@ -95,5 +95,24 @@ public interface IExtensionPoint<T extends Record>
@SuppressWarnings("JavadocReference") // reference to NetworkConstants, ForgeHooksClient
record DisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) implements IExtensionPoint<DisplayTest> {
public static final String IGNORESERVERONLY = "OHNOES\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31";
/**
* Ignores any version information coming from the server - use for server only mods
*/
public static final Supplier<DisplayTest> IGNORE_SERVER_VERSION = () -> new DisplayTest(IGNORESERVERONLY, (remoteVersion, isFromServer) -> true);
/**
* Ignores all information and provides no information
*/
public static final Supplier<DisplayTest> IGNORE_ALL_VERSION = () -> new DisplayTest("", (remoteVersion, isFromServer) -> true);
/**
* An optional alternative to {@link #DisplayTest(Supplier, BiPredicate)} which accepts a constant version string
* instead of a {@link Supplier}.
* <p>Internally, the provided version string is wrapped in a Supplier for you.</p>
*/
public DisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
this(() -> version, remoteVersionTest);
}
}
}
@@ -9,6 +9,7 @@ import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.IModBusEvent;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.progress.ProgressMeter;
import net.minecraftforge.forgespi.language.IModInfo;
@@ -21,6 +22,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -58,15 +60,16 @@ public abstract class ModContainer
this.modInfo = info;
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
final String displayTestString = info.getConfig().<String>getConfigElement("displayTest").orElse("MATCH_VERSION"); // missing defaults to DEFAULT type
final String displayTestString = info.getConfig().<String>getConfigElement("displayTest")
.orElseGet(() -> (Boolean) info.getOwningFile().getFileProperties().getOrDefault(ModFileInfo.CLIENT_SIDE_ONLY_PROP, Boolean.FALSE) ? "IGNORE_ALL_VERSION" : "MATCH_VERSION");
Supplier<IExtensionPoint.DisplayTest> displayTestSupplier = switch (displayTestString) {
case "MATCH_VERSION" -> // default displaytest checks for version string match
() -> new IExtensionPoint.DisplayTest(() -> this.modInfo.getVersion().toString(),
(incoming, isNetwork) -> Objects.equals(incoming, this.modInfo.getVersion().toString()));
case "IGNORE_SERVER_VERSION" -> // Ignores any version information coming from the server - use for server only mods
() -> new IExtensionPoint.DisplayTest(() -> IExtensionPoint.DisplayTest.IGNORESERVERONLY, (incoming, isNetwork) -> true);
IExtensionPoint.DisplayTest.IGNORE_SERVER_VERSION;
case "IGNORE_ALL_VERSION" -> // Ignores all information and provides no information
() -> new IExtensionPoint.DisplayTest(() -> "", (incoming, isNetwork) -> true);
IExtensionPoint.DisplayTest.IGNORE_ALL_VERSION;
case "NONE" -> null; // NO display test at all - use this if you're going to do your own display test
default -> // any other value throws an exception
throw new IllegalArgumentException("Invalid displayTest value supplied in mods.toml");
@@ -145,6 +148,22 @@ public abstract class ModContainer
extensionPoints.put(point, extension);
}
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> displayTest);
}
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
registerExtensionPoint(IExtensionPoint.DisplayTest.class, displayTest);
}
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
}
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
}
public void addConfig(final ModConfig modConfig) {
configs.put(modConfig.getType(), modConfig);
}
@@ -8,38 +8,54 @@ package net.minecraftforge.fml;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.config.IConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.loading.FMLLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.BiPredicate;
import java.util.function.Supplier;
public class ModLoadingContext
{
private static final Logger LOGGER = LogUtils.getLogger();
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
private ModContainer activeContainer;
private Object languageExtension;
private ModLoadingStage stage;
/**
* @deprecated Use the context provided by your language loader in your mod's constructor.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public static ModLoadingContext get() {
return context.get();
}
private ModContainer activeContainer;
/**
* @deprecated Going to be moved to ForgeHooks for internal use.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public void setActiveContainer(final ModContainer container) {
this.activeContainer = container;
this.languageExtension = container == null ? null : container.contextExtension.get();
}
/**
* Going to be moved to ForgeHooks for internal use.
* @deprecated Override/Use {@link ModLoadingContext#getContainer()}
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public ModContainer getActiveContainer() {
return activeContainer == null ? ModList.get().getModContainerById("minecraft").orElseThrow(()->new RuntimeException("Where is minecraft???!")) : activeContainer;
}
@Deprecated(forRemoval = true, since = "1.21.1")
public String getActiveNamespace() {
return activeContainer == null ? "minecraft" : activeContainer.getNamespace();
}
public ModContainer getContainer() {
return getActiveContainer();
}
/**
* Register an {@link IExtensionPoint} with the mod container.
* @param point The extension point to register
@@ -47,29 +63,67 @@ public class ModLoadingContext
* @param <T> The type signature of the extension operator
*/
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension) {
getActiveContainer().registerExtensionPoint(point, extension);
getContainer().registerExtensionPoint(point, extension);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)}.</p>
* @param displayTest The {@link IExtensionPoint.DisplayTest} to register
*/
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
getContainer().registerDisplayTest(() -> displayTest);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest supplier with {@link #registerExtensionPoint(Class, Supplier)}.</p>
* @param displayTest The {@link Supplier<IExtensionPoint.DisplayTest>} to register
*/
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
getContainer().registerDisplayTest(displayTest);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
* creates the DisplayTest instance for you using the provided parameters.</p>
* @see IExtensionPoint.DisplayTest#DisplayTest(String, BiPredicate)
*/
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
* creates the DisplayTest instance for you using the provided parameters.</p>
* @see IExtensionPoint.DisplayTest#DisplayTest(Supplier, BiPredicate)
*/
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getActiveContainer().getModId());
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getContainer().getModId());
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
getContainer().addConfig(new ModConfig(type, spec, getContainer()));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec, String fileName) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getActiveContainer().getModId(), fileName);
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getContainer().getModId(), fileName);
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
getContainer().addConfig(new ModConfig(type, spec, getContainer(), fileName));
}
@@ -51,8 +51,8 @@ public class VersionChecker
BETA(),
BETA_OUTDATED(6, true);
final int sheetOffset;
final boolean draw, animated;
private final int sheetOffset;
private final boolean draw, animated;
Status()
{
@@ -91,6 +91,9 @@ public class VersionChecker
return animated;
}
public boolean isOutdated() {
return this == OUTDATED || this == BETA_OUTDATED;
}
}
public record CheckResult(VersionChecker.Status status, ComparableVersion target, Map<ComparableVersion, String> changes, String url) {}
@@ -257,7 +260,7 @@ public class VersionChecker
LOGGER.warn("Failed to process update information", e);
status = FAILED;
}
results.put(mod, new CheckResult(status, target, changes, display_url));
RESULTS.put(mod, new CheckResult(status, target, changes, display_url));
}
}.start();
}
@@ -273,12 +276,12 @@ public class VersionChecker
return ret;
}
private static Map<IModInfo, CheckResult> results = new ConcurrentHashMap<>();
private static final Map<IModInfo, CheckResult> RESULTS = new ConcurrentHashMap<>();
private static final CheckResult PENDING_CHECK = new CheckResult(PENDING, null, null, null);
public static CheckResult getResult(IModInfo mod)
{
return results.getOrDefault(mod, PENDING_CHECK);
return RESULTS.getOrDefault(mod, PENDING_CHECK);
}
}
@@ -14,9 +14,7 @@ import net.minecraftforge.fml.loading.ImmediateWindowProvider;
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.stb.STBImage;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.tinyfd.TinyFileDialogs;
@@ -30,9 +28,8 @@ import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -40,15 +37,16 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
@@ -78,7 +76,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
private static final Logger LOGGER = LoggerFactory.getLogger("EARLYDISPLAY");
private final AtomicBoolean animationTimerTrigger = new AtomicBoolean(true);
private ColourScheme colourScheme;
private ColourScheme colourScheme = ColourScheme.RED;
private ElementShader elementShader;
private RenderElement.DisplayContext context;
@@ -86,6 +84,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
private int framecount;
private EarlyFramebuffer framebuffer;
private ScheduledFuture<?> windowTick;
private ScheduledFuture<?> initializationFuture;
private PerformanceInfo performanceInfo;
private ScheduledFuture<?> performanceTick;
@@ -134,13 +133,17 @@ public class DisplayWindow implements ImmediateWindowProvider {
this.colourScheme = ColourScheme.BLACK;
} else {
try {
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Paths.get("options.txt")));
var options = optionLines.stream().map(l -> l.split(":")).filter(a -> a.length == 2).collect(Collectors.toMap(a -> a[0], a -> a[1]));
var colourScheme = Boolean.parseBoolean(options.getOrDefault("darkMojangStudiosBackground", "false"));
this.colourScheme = colourScheme ? ColourScheme.BLACK : ColourScheme.RED;
} catch (IOException ioe) {
// No options
this.colourScheme = ColourScheme.RED; // default to red colourscheme
// check the options file for the colour scheme
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Path.of("options.txt")));
var keyName = "darkMojangStudiosBackground:";
for (String line : optionLines) {
if (line.startsWith(keyName)) {
this.colourScheme = line.startsWith("true", keyName.length()) ? ColourScheme.BLACK : ColourScheme.RED;
break;
}
}
} catch (IOException e) {
this.colourScheme = ColourScheme.RED; // fallback to red colourScheme
}
}
this.maximized = parsed.has(maximizedopt) || FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_MAXIMIZED);
@@ -225,7 +228,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
LOGGER.error("Crash during font initialization", t);
crashElegantly("An error occurred initializing a font for rendering. "+t.getMessage());
}
this.elements = new ArrayList<>(Arrays.asList(
this.elements = new ArrayList<>(List.of(
RenderElement.anvil(font),
RenderElement.logMessageOverlay(font),
RenderElement.forgeVersionOverlay(font, mcVersion+"-"+forgeVersion.split("-")[0]),
@@ -264,7 +267,6 @@ public class DisplayWindow implements ImmediateWindowProvider {
public void render(int alpha) {
var currentVAO = glGetInteger(GL_VERTEX_ARRAY_BINDING);
var currentFB = glGetInteger(GL_READ_FRAMEBUFFER_BINDING);
glfwSwapInterval(0);
glViewport(0, 0, this.context.scaledWidth(), this.context.scaledHeight());
RenderElement.globalAlpha = alpha;
framebuffer.activate();
@@ -287,7 +289,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
return thread;
});
initWindow(mcVersion);
renderScheduler.schedule(() -> initRender(mcVersion, forgeVersion), 1, TimeUnit.MILLISECONDS);
this.initializationFuture = renderScheduler.schedule(() -> initRender(mcVersion, forgeVersion), 1, TimeUnit.MILLISECONDS);
return this::periodicTick;
}
@@ -360,14 +362,15 @@ public class DisplayWindow implements ImmediateWindowProvider {
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
if (mcVersion != null) {
// this emulates what we would get without early progress window
// as vanilla never sets these, so GLFW uses the first window title
// set them explicitly to avoid it using "FML early loading progress" as the class
String vanillaWindowTitle = "Minecraft* " + mcVersion;
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
}
String vanillaWindowTitle = "Minecraft* ";
if (mcVersion != null) vanillaWindowTitle += mcVersion;
// this emulates what we would get without early progress window
// as vanilla never sets these, so GLFW uses the first window title
// set them explicitly to avoid it using "FML early loading progress" as the class
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
long primaryMonitor = glfwGetPrimaryMonitor();
if (primaryMonitor == 0) {
@@ -389,7 +392,8 @@ public class DisplayWindow implements ImmediateWindowProvider {
}, 10, TimeUnit.SECONDS);
int versidx = 0;
var skipVersions = FMLConfig.<String>getListConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SKIP_GL_VERSIONS);
final String[] lastGLError=new String[GL_VERSIONS.length];
boolean showHelpLog = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_LOG_HELP_MSG);
final String[] lastGLError = new String[GL_VERSIONS.length];
do {
final var glVersionToTry = GL_VERSIONS[versidx][0] + "." + GL_VERSIONS[versidx][1];
if (skipVersions.contains(glVersionToTry)) {
@@ -398,11 +402,23 @@ public class DisplayWindow implements ImmediateWindowProvider {
continue;
}
LOGGER.info("Trying GL version " + glVersionToTry);
if (showHelpLog && versidx == 0) {
LOGGER.info("""
If this message is the only thing at the bottom of your log before a crash, you probably have a driver issue.
Possible solutions:
A) Make sure Minecraft is set to prefer high performance graphics in the OS and/or driver control panel
B) Check for driver updates on the graphics brand's website
C) Try reinstalling your graphics drivers
D) If still not working after trying all of the above, ask for further help on the Forge forums or Discord
You can safely ignore this message if the game starts up successfully.""");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_VERSIONS[versidx][0]); // we try our versions one at a time
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_VERSIONS[versidx][1]);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
window = glfwCreateWindow(winWidth, winHeight, "Minecraft: Forge Loading...", 0L, 0L);
window = glfwCreateWindow(winWidth, winHeight, vanillaWindowTitle, 0L, 0L);
var erridx = versidx;
handleLastGLFWError((error, description) -> lastGLError[erridx] = String.format("Trying %d.%d: GLFW error: [0x%X]%s", GL_VERSIONS[erridx][0], GL_VERSIONS[erridx][1], error, description));
if (lastGLError[versidx] != null) {
@@ -430,6 +446,9 @@ public class DisplayWindow implements ImmediateWindowProvider {
this.glVersion = gotVersion;
this.window = window;
if (showHelpLog)
FMLConfig.updateConfig(FMLConfig.ConfigValue.EARLY_WINDOW_LOG_HELP_MSG, false);
int[] x = new int[1];
int[] y = new int[1];
glfwGetMonitorPos(primaryMonitor, x, y);
@@ -447,19 +466,19 @@ public class DisplayWindow implements ImmediateWindowProvider {
glfwSetWindowPos(window, (vidmode.width() - this.winWidth) / 2 + monitorX, (vidmode.height() - this.winHeight) / 2 + monitorY);
// Attempt setting the icon
int[] channels = new int[1];
try (var glfwImgBuffer = GLFWImage.create(MemoryUtil.getAllocator().malloc(GLFWImage.SIZEOF), 1)) {
final ByteBuffer imgBuffer;
try (GLFWImage glfwImages = GLFWImage.malloc()) {
imgBuffer = STBHelper.loadImageFromClasspath("forge_logo.png", 20000, x, y, channels);
glfwImgBuffer.put(glfwImages.set(x[0], y[0], imgBuffer));
glfwSetWindowIcon(window, glfwImgBuffer);
STBImage.stbi_image_free(imgBuffer);
}
} catch (NullPointerException e) {
System.err.println("Failed to load forge logo");
}
handleLastGLFWError((error, description) -> LOGGER.debug(String.format("Suppressing GLFW icon error: [0x%X]%s", error, description)));
// int[] channels = new int[1];
// try (var glfwImgBuffer = GLFWImage.create(MemoryUtil.getAllocator().malloc(GLFWImage.SIZEOF), 1)) {
// final ByteBuffer imgBuffer;
// try (GLFWImage glfwImages = GLFWImage.malloc()) {
// imgBuffer = STBHelper.loadImageFromClasspath("forge_logo.png", 20000, x, y, channels);
// glfwImgBuffer.put(glfwImages.set(x[0], y[0], imgBuffer));
// glfwSetWindowIcon(window, glfwImgBuffer);
// STBImage.stbi_image_free(imgBuffer);
// }
// } catch (NullPointerException e) {
// System.err.println("Failed to load forge logo");
// }
// handleLastGLFWError((error, description) -> LOGGER.debug(String.format("Suppressing GLFW icon error: [0x%X]%s", error, description)));
glfwSetFramebufferSizeCallback(window, this::fbResize);
glfwSetWindowPosCallback(window, this::winMove);
@@ -518,6 +537,16 @@ public class DisplayWindow implements ImmediateWindowProvider {
* @return the Window we own.
*/
public long setupMinecraftWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, final LongSupplier monitorSupplier) {
// wait for the window to actually be initialized
try {
this.initializationFuture.get(30, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
Thread.dumpStack();
crashElegantly("We seem to be having trouble initializing the window, waited for 30 seconds");
}
// we have to spin wait for the window ticker
ImmediateWindowHandler.updateProgress("Initializing Game Graphics");
while (!this.windowTick.isDone()) {
@@ -584,8 +613,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
var fm = layer.findModule("forge").orElseThrow();
getClass().getModule().addReads(fm);
var clz = FMLLoader.getGameLayer().findModule("forge").map(l->Class.forName(l, "net.minecraftforge.client.loading.ForgeLoadingOverlay")).orElseThrow();
var methods = Arrays.stream(clz.getMethods()).filter(m-> Modifier.isStatic(m.getModifiers())).collect(Collectors.toMap(Method::getName, Function.identity()));
loadingOverlay = methods.get("newInstance");
loadingOverlay = Arrays.stream(clz.getMethods()).filter(m-> Modifier.isStatic(m.getModifiers()) && m.getName().equals("newInstance")).findFirst().orElseThrow();
}
public int getFramebufferTextureId() {
@@ -6,35 +6,44 @@
package net.minecraftforge.fml.earlydisplay;
import com.sun.management.OperatingSystemMXBean;
import net.minecraftforge.fml.loading.FMLConfig;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
public class PerformanceInfo {
private static final MemoryMXBean MEMORY_BEAN = ManagementFactory.getMemoryMXBean();
private final boolean showCPUUsage;
private final OperatingSystemMXBean osBean;
private final MemoryMXBean memoryBean;
float memory;
private String text;
PerformanceInfo() {
osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
memoryBean = ManagementFactory.getMemoryMXBean();
showCPUUsage = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SHOW_CPU);
osBean = showCPUUsage ? ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class) : null;
}
void update() {
final MemoryUsage heapusage = memoryBean.getHeapMemoryUsage();
final MemoryUsage heapusage = MEMORY_BEAN.getHeapMemoryUsage();
memory = (float) heapusage.getUsed() / heapusage.getMax();
if (!showCPUUsage) {
text = "Memory: %d/%dMB (%.1f%%)".formatted(heapusage.getUsed() >>> 20, heapusage.getMax() >>> 20, memory * 100f);
return;
}
var cpuLoad = osBean.getProcessCpuLoad();
String cpuText;
if (cpuLoad == -1) {
cpuText = String.format("*CPU: %.1f%%", osBean.getCpuLoad() * 100f);
cpuText = "*CPU: %.1f%%".formatted(osBean.getCpuLoad() * 100f);
} else {
cpuText = String.format("CPU: %.1f%%", cpuLoad * 100f);
cpuText = "CPU: %.1f%%".formatted(cpuLoad * 100f);
}
text = String.format("Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s", heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20, cpuText);
text = "Memory: %d/%dMB (%.1f%%) %s".formatted(heapusage.getUsed() >>> 20, heapusage.getMax() >>> 20, memory * 100f, cpuText);
}
String text() {
@@ -34,11 +34,14 @@ public class RenderElement {
};
}
}
@FunctionalInterface
interface TextureRenderer {
void accept(SimpleBufferBuilder bb, DisplayContext context, int[] size, int frame);
}
@FunctionalInterface
interface Initializer extends Supplier<Renderer> {}
@FunctionalInterface
interface TextGenerator {
void accept(SimpleBufferBuilder bb, SimpleFont fh, DisplayContext ctx);
}
@@ -201,14 +204,17 @@ public class RenderElement {
bar.then(label).accept(buffer, context, frameNumber);
}
@FunctionalInterface
interface ColourFunction {
int colour(int frame);
}
@FunctionalInterface
interface ProgressDisplay {
float[] progress(int frame);
}
@FunctionalInterface
interface BarPosition {
int[] location(DisplayContext context);
}
@@ -280,7 +286,7 @@ public class RenderElement {
if (num < min) {
return min;
} else {
return num > max ? max : num;
return Math.min(num, max);
}
}
@@ -288,7 +294,7 @@ public class RenderElement {
if (num < min) {
return min;
} else {
return num > max ? max : num;
return Math.min(num, max);
}
}
+1 -1
View File
@@ -77,7 +77,7 @@ jar.doFirst {
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked'
options.compilerArgs << '-Xlint:-unchecked'
}
license {
@@ -36,9 +36,9 @@ import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
*/
public class CapabilityTokenSubclass implements ILaunchPluginService {
private final String FUNC_NAME = "getType";
private final String FUNC_DESC = "()Ljava/lang/String;";
private final String CAP_INJECT = "net/minecraftforge/common/capabilities/CapabilityToken"; //Don't directly reference this to prevent class loading.
private static final String FUNC_NAME = "getType";
private static final String FUNC_DESC = "()Ljava/lang/String;";
private static final String CAP_INJECT = "net/minecraftforge/common/capabilities/CapabilityToken"; //Don't directly reference this to prevent class loading.
@Override
public String name() {
@@ -51,7 +51,14 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
{
return isEmpty ? NAY : YAY;
if (isEmpty)
return NAY;
String internalName = classType.getInternalName();
if (internalName.startsWith("net/minecraft/") || internalName.startsWith("com/mojang/"))
return NAY;
return YAY;
}
@Override
@@ -75,7 +82,7 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
SignatureReader reader = new SignatureReader(classNode.signature); // Having a node version of this would probably be useful.
reader.accept(new SignatureVisitor(Opcodes.ASM9)
{
Deque<String> stack = new ArrayDeque<>();
final Deque<String> stack = new ArrayDeque<>();
@Override
public void visitClassType(final String name)
@@ -113,7 +120,7 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
}
}
private static class Holder {
private static final class Holder {
String value;
}
@@ -8,6 +8,7 @@ package net.minecraftforge.fml.common.asm;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -35,7 +36,11 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
new VanillaObjectHolderData("net.minecraft.core.particles.ParticleTypes", "particle_type", "net.minecraft.core.particles.ParticleType"),
new VanillaObjectHolderData("net.minecraft.sounds.SoundEvents", "sound_event", "net.minecraft.sounds.SoundEvent")
).collect(Collectors.toMap(VanillaObjectHolderData::holderClass, Function.identity()));
private final String OBJECT_HOLDER = "Lnet/minecraftforge/registries/ObjectHolder;"; //Don't directly reference this to prevent class loading.
private static final Set<String> VANILLA_OBJECT_HOLDER_CLASSES = VANILLA_OBJECT_HOLDERS.keySet().stream()
.map(it -> it.replace('.', '/'))
.collect(Collectors.toUnmodifiableSet());
private static final String OBJECT_HOLDER = "Lnet/minecraftforge/registries/ObjectHolder;"; //Don't directly reference this to prevent class loading.
private static final int PUBLIC_STATIC_FINAL_FLAGS = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
@Override
public String name() {
@@ -46,13 +51,30 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
{
return isEmpty ? NAY : YAY;
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
if (isEmpty)
return NAY;
// Let's skip processing classes that definitely don't have object holders
String internalName = classType.getInternalName();
// Forge classes that aren't in the debug package (that package is used for tests)
if (internalName.startsWith("net/minecraftforge/") && !internalName.substring(18).contains("debug")
&& !internalName.equals("net/minecraftforge/common/crafting/ConditionalRecipe"))
return NAY;
// Vanilla classes that don't have object holders
if (internalName.startsWith("com/mojang/"))
return NAY;
// ...except specific ones we added to the VANILLA_OBJECT_HOLDERS map
if (internalName.startsWith("net/minecraft/") && !VANILLA_OBJECT_HOLDER_CLASSES.contains(internalName))
return NAY;
return YAY;
}
private boolean hasHolder(List<AnnotationNode> lst)
{
private boolean hasHolder(List<AnnotationNode> lst) {
return lst != null && lst.stream().anyMatch(n -> n.desc.equals(OBJECT_HOLDER));
}
@@ -75,10 +97,9 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
{
final AtomicBoolean changes = new AtomicBoolean();
//Must be public static finals, and non-array objects
final int flags = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
//Fix Annotated Fields before injecting from class level
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L") && hasHolder(f.visibleAnnotations)).forEach(f ->
classNode.fields.stream().filter(f -> ((f.access & PUBLIC_STATIC_FINAL_FLAGS) == PUBLIC_STATIC_FINAL_FLAGS) && f.desc.startsWith("L") && hasHolder(f.visibleAnnotations)).forEach(f ->
{
int prev = f.access;
f.access &= ~Opcodes.ACC_FINAL; //Strip final
@@ -88,7 +109,7 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
if (VANILLA_OBJECT_HOLDERS.containsKey(classType.getClassName())) //Class level, de-finalize all fields and add @ObjectHolder to them!
{
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L")).forEach(f ->
classNode.fields.stream().filter(f -> ((f.access & PUBLIC_STATIC_FINAL_FLAGS) == PUBLIC_STATIC_FINAL_FLAGS) && f.desc.startsWith("L")).forEach(f ->
{
int prev = f.access;
f.access &= ~Opcodes.ACC_FINAL;
@@ -30,15 +30,16 @@ import org.slf4j.MarkerFactory;
public class RuntimeEnumExtender implements ILaunchPluginService {
private static final Logger LOGGER = LogUtils.getLogger();
private final Type STRING = Type.getType(String.class);
private final Type ENUM = Type.getType(Enum.class);
private final Type MARKER_IFACE = Type.getType("Lnet/minecraftforge/common/IExtensibleEnum;");
private final Type ARRAY_UTILS = Type.getType("Lorg/apache/commons/lang3/ArrayUtils;"); //Don't directly reference this to prevent class loading.
private final String ADD_DESC = Type.getMethodDescriptor(Type.getType(Object[].class), Type.getType(Object[].class), Type.getType(Object.class));
private final Type UNSAFE_HACKS = Type.getType("Lnet/minecraftforge/fml/unsafe/UnsafeHacks;"); //Again, not direct reference to prevent class loading.
private final String CLEAN_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Class.class));
private final String NAME_DESC = Type.getMethodDescriptor(STRING);
private final String EQUALS_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, STRING);
private static final Type STRING = Type.getType(String.class);
private static final Type ENUM = Type.getType(Enum.class);
private static final Type MARKER_IFACE = Type.getType("Lnet/minecraftforge/common/IExtensibleEnum;");
private static final Type ARRAY_UTILS = Type.getType("Lorg/apache/commons/lang3/ArrayUtils;"); //Don't directly reference this to prevent class loading.
private static final String ADD_DESC = Type.getMethodDescriptor(Type.getType(Object[].class), Type.getType(Object[].class), Type.getType(Object.class));
private static final Type UNSAFE_HACKS = Type.getType("Lnet/minecraftforge/fml/unsafe/UnsafeHacks;"); //Again, not direct reference to prevent class loading.
private static final String CLEAN_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Class.class));
private static final String NAME_DESC = Type.getMethodDescriptor(STRING);
private static final String EQUALS_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, STRING);
private static final int FLAGS = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
@Override
public String name() {
@@ -49,9 +50,15 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
{
return isEmpty ? NAY : YAY;
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
if (isEmpty)
return NAY;
String internalName = classType.getInternalName();
if (internalName.startsWith("net/minecraftforge/") || internalName.startsWith("com/mojang/"))
return NAY;
return YAY;
}
@Override
@@ -60,25 +67,24 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
if ((classNode.access & Opcodes.ACC_ENUM) == 0)
return ComputeFlags.NO_REWRITE;
Type array = Type.getType("[" + classType.getDescriptor());
final int flags = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
FieldNode values = classNode.fields.stream().filter(f -> f.desc.contentEquals(array.getDescriptor()) && ((f.access & flags) == flags)).findFirst().orElse(null);
if (!classNode.interfaces.contains(MARKER_IFACE.getInternalName())) {
if (!classNode.interfaces.contains(MARKER_IFACE.getInternalName()))
return ComputeFlags.NO_REWRITE;
}
Type array = Type.getType("[" + classType.getDescriptor());
String arrayDesc = array.getDescriptor();
FieldNode values = classNode.fields.stream().filter(f -> f.desc.equals(arrayDesc) && ((f.access & FLAGS) == FLAGS)).findFirst().orElse(null);
//Static methods named "create" with first argument as a string
List<MethodNode> candidates = classNode.methods.stream()
.filter(m -> ((m.access & Opcodes.ACC_STATIC) != 0) && m.name.equals("create"))
.collect(Collectors.toList());
.toList();
if (candidates.isEmpty()) {
throw new IllegalStateException("IExtensibleEnum has no candidate factory methods: " + classType.getClassName());
}
candidates.forEach(mtd ->
for (var mtd : candidates)
{
Type[] args = Type.getArgumentTypes(mtd.desc);
if (args.length == 0 || !args[0].equals(STRING)) {
@@ -110,8 +116,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
Type[] ctrArgs = new Type[args.length + 1];
ctrArgs[0] = STRING;
ctrArgs[1] = Type.INT_TYPE;
for (int x = 1; x < args.length; x++)
ctrArgs[1 + x] = args[x];
System.arraycopy(args, 1, ctrArgs, 2, args.length - 1);
String desc = Type.getMethodDescriptor(Type.VOID_TYPE, ctrArgs);
@@ -233,7 +238,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
ins.load(vars, classType);
ins.areturn(classType);
}
});
}
return ComputeFlags.COMPUTE_FRAMES;
}
@@ -36,7 +36,9 @@ public class FMLConfig
EARLY_WINDOW_FBSCALE("earlyWindowFBScale", 1, "Early window framebuffer scale"),
EARLY_WINDOW_MAXIMIZED("earlyWindowMaximized", Boolean.FALSE, "Early window starts maximized"),
EARLY_WINDOW_SKIP_GL_VERSIONS("earlyWindowSkipGLVersions", List.of(), "Skip specific GL versions, may help with buggy graphics card drivers"),
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?")
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?"),
EARLY_WINDOW_SHOW_CPU("earlyWindowShowCPU", Boolean.FALSE, "Whether to show CPU usage stats in early window"),
EARLY_WINDOW_LOG_HELP_MSG("earlyWindowLogHelpMessage", Boolean.TRUE, "Whether to log a help message on first attempt, to aid troubleshooting. This setting should automatically disable itself after a successful launch"),
;
private final String entry;
@@ -65,6 +65,9 @@ public class FMLLoader
throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion());
}
// Allows us to communicate properties with other services through ModLauncher
setupBlackboardKeys();
accessTransformer = (AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
LOGGER.error(CORE, "Access Transformer library is missing, we need this to run");
return new IncompatibleEnvironmentException("Missing AccessTransformer, cannot run");
@@ -126,6 +129,12 @@ public class FMLLoader
}
}
private static void setupBlackboardKeys() {
LOGGER.debug(CORE, "Requesting CoreMods to not apply the fix for ASMAPI.findFirstInstructionBefore by default");
var blackboardKey = TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "coremods.use_old_findFirstInstructionBefore", Boolean.class);
Launcher.INSTANCE.blackboard().<Boolean>computeIfAbsent(blackboardKey, k -> true);
}
static void setupLaunchHandler(final IEnvironment environment, final Map<String, Object> arguments)
{
final String launchTarget = environment.getProperty(IEnvironment.Keys.LAUNCHTARGET.get()).orElse("MISSING");
@@ -147,7 +147,7 @@ public class RuntimeDistCleaner implements ILaunchPluginService
return ret;
}
private boolean remove(final List<AnnotationNode> anns, final String side)
private static boolean remove(final List<AnnotationNode> anns, final String side)
{
return unpack(anns).stream().
filter(ann->Objects.equals(ann.desc, ONLYIN)).
@@ -169,9 +169,15 @@ public class RuntimeDistCleaner implements ILaunchPluginService
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
{
return isEmpty ? NAY : YAY;
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
if (isEmpty)
return NAY;
String internalName = classType.getInternalName();
if (internalName.startsWith("net/minecraftforge/"))
return NAY;
return YAY;
}
private static class LambdaGatherer extends MethodVisitor {
@@ -18,12 +18,15 @@ import java.util.function.BiPredicate;
public class VersionSupportMatrix {
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
static {
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
// 1.19.2 is Compatible with 1.19.1
add("languageloader.javafml", "42");
add("mod.minecraft", "1.19.1");
add("mod.forge", "42.0.9");
// final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
// if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
// // 1.19.2 is Compatible with 1.19.1
// add("languageloader.javafml", "42");
// add("mod.minecraft", "1.19.1");
// add("mod.forge", "42.0.9");
// }
if (FMLLoader.versionInfo().mcVersion().equals("1.20.1")) {
add("mod.forge", "47.1.79");
}
}
private static void add(String key, String value) {
@@ -34,6 +34,11 @@ public abstract class AbstractModProvider implements IModProvider
protected static final String MANIFEST = "META-INF/MANIFEST.MF";
protected IModLocator.ModFileOrException createMod(Path... path) {
return this.createMod(getDefaultJarModType(), path);
}
// FORGE: Backporting artifact, the defaultType must be the first parameter since path is varargs
protected IModLocator.ModFileOrException createMod(String defaultType, Path... path) {
var mjm = new ModJarMetadata();
var sj = SecureJar.from(
Manifest::new,
@@ -45,7 +50,7 @@ public abstract class AbstractModProvider implements IModProvider
IModFile mod;
var type = sj.moduleDataProvider().getManifest().getMainAttributes().getValue(ModFile.TYPE);
if (type == null) {
type = getDefaultJarModType();
type = defaultType;
}
if (sj.moduleDataProvider().findFile(MODS_TOML).isPresent()) {
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, path);
@@ -81,7 +81,14 @@ public class JarInJarDependencyLocator extends AbstractJarFileDependencyLocator
final Map<String, ?> outerFsArgs = ImmutableMap.of("packagePath", pathInModFile);
final FileSystem zipFS = FileSystems.newFileSystem(filePathUri, outerFsArgs);
final Path pathInFS = zipFS.getPath("/");
return Optional.of(createMod(pathInFS).file());
final IModFile.Type parentType = file.getType();
final String modType;
if (parentType == IModFile.Type.LIBRARY || parentType == IModFile.Type.LANGPROVIDER) {
modType = IModFile.Type.LIBRARY.name();
} else {
modType = IModFile.Type.GAMELIBRARY.name();
}
return Optional.of(createMod(modType, pathInFS).file());
}
catch (Exception e)
{
@@ -12,6 +12,7 @@ import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.api.IModuleLayerManager;
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
import net.minecraftforge.fml.loading.EarlyLoadingException;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.ImmediateWindowHandler;
import net.minecraftforge.fml.loading.LogMarkers;
import net.minecraftforge.fml.loading.UniqueModListBuilder;
@@ -21,6 +22,7 @@ import net.minecraftforge.forgespi.language.IModFileInfo;
import net.minecraftforge.forgespi.locating.IDependencyLocator;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.util.ArrayList;
@@ -67,6 +69,7 @@ public class ModDiscoverer {
List<EarlyLoadingException.ExceptionData> discoveryErrorData = new ArrayList<>();
boolean successfullyLoadedMods = true;
List<IModFileInfo> brokenFiles = new ArrayList<>();
boolean distIsDedicatedServer = FMLLoader.getDist().isDedicatedServer();
ImmediateWindowHandler.updateProgress("Discovering mod files");
//Loop all mod locators to get the prime mods to load from.
for (IModLocator locator : modLocatorList) {
@@ -85,8 +88,24 @@ public class ModDiscoverer {
if (!badModFiles.isEmpty()) {
LOGGER.error(LogMarkers.SCAN, "Locator {} returned {} files which is are not ModFile instances! They will be skipped!", locator, badModFiles.size());
brokenFiles.addAll(badModFiles.stream().map(IModFile::getModFileInfo).toList());
locatedFiles.removeAll(badModFiles);
}
locatedFiles.removeAll(badModFiles);
if (distIsDedicatedServer) {
var clientOnlyModFiles = locatedFiles.stream()
.filter(file -> {
// some mod files can have null infos, like javafml, mclanguage, lowcode, and fmlcore
@Nullable var info = file.getModFileInfo();
return info != null && (Boolean) info.getFileProperties().getOrDefault(ModFileInfo.CLIENT_SIDE_ONLY_PROP, Boolean.FALSE);
})
.toList();
if (!clientOnlyModFiles.isEmpty()) {
LOGGER.warn(LogMarkers.SCAN, "Locator {} returned {} files which are client-side-only mods, but we're on a dedicated server. They will be skipped!", locator, clientOnlyModFiles.size());
locatedFiles.removeAll(clientOnlyModFiles);
}
}
LOGGER.debug(LogMarkers.SCAN, "Locator {} found {} valid mod files", locator, locatedFiles.size());
handleLocatedFiles(loadedFiles, locatedFiles);
} catch (InvalidModFileException imfe) {
@@ -29,6 +29,7 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -50,6 +51,10 @@ public class ModFileInfo implements IModFileInfo, IConfigurable
private final String license;
private final List<String> usesServices;
public static final String CLIENT_SIDE_ONLY_PROP = "__FORGE_clientSideOnly";
private static final Map<String, Object> CLIENT_SIDE_ONLY_MAP = Map.of(CLIENT_SIDE_ONLY_PROP, Boolean.TRUE);
ModFileInfo(final ModFile modFile, final IConfigurable config, Consumer<IModFileInfo> configFileConsumer)
{
this.modFile = modFile;
@@ -68,10 +73,23 @@ public class ModFileInfo implements IModFileInfo, IConfigurable
.orElse("");
this.showAsResourcePack = config.<Boolean>getConfigElement("showAsResourcePack")
.orElse(false);
boolean clientSideOnly = config.<Boolean>getConfigElement("clientSideOnly")
.orElse(false);
this.usesServices = config.<List<String>>getConfigElement("services")
.orElse(List.of());
this.properties = config.<Map<String, Object>>getConfigElement("properties")
.orElse(Collections.emptyMap());
var maybeProps = config.<Map<String, Object>>getConfigElement("properties");
if (clientSideOnly) {
if (maybeProps.isPresent()) {
this.properties = new HashMap<>(maybeProps.get());
this.properties.put(CLIENT_SIDE_ONLY_PROP, Boolean.TRUE);
} else {
this.properties = CLIENT_SIDE_ONLY_MAP;
}
} else {
this.properties = maybeProps.orElse(Collections.emptyMap());
}
this.modFile.setFileProperties(this.properties);
this.issueURL = config.<String>getConfigElement("issueTrackerURL")
.map(StringUtils::toURL)
@@ -80,7 +80,8 @@ public class ModInfo implements IModInfo, IConfigurable
this.displayName = config.<String>getConfigElement("displayName")
.orElse(this.modId);
this.description = config.<String>getConfigElement("description")
.orElse("MISSING DESCRIPTION");
.orElse("MISSING DESCRIPTION")
.replace("\r\n", "\n").stripIndent();
this.logoFile = Optional.ofNullable(config.<String>getConfigElement("logoFile")
.orElseGet(() -> ownFile.flatMap(mf -> mf.<String>getConfigElement("logoFile"))
.orElse(null)));
@@ -205,7 +206,7 @@ public class ModInfo implements IModInfo, IConfigurable
private final boolean mandatory;
private final Ordering ordering;
private final DependencySide side;
private Optional<URL> referralUrl;
private final Optional<URL> referralUrl;
public ModVersion(final IModInfo owner, final IConfigurable config) {
this.owner = owner;
@@ -6,6 +6,7 @@
package net.minecraftforge.fml.loading.moddiscovery;
import com.mojang.logging.LogUtils;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.modlauncher.api.IModuleLayerManager;
import cpw.mods.modlauncher.api.ITransformationService;
import net.minecraftforge.fml.loading.*;
@@ -26,14 +27,17 @@ public class ModValidator {
private final Map<IModFile.Type, List<ModFile>> modFiles;
private final List<ModFile> candidatePlugins;
private final List<ModFile> candidateMods;
private final List<ModFile> gameLibraries;
private LoadingModList loadingModList;
private List<IModFile> brokenFiles;
private final List<IModFile> brokenFiles;
private final List<EarlyLoadingException.ExceptionData> discoveryErrorData;
public ModValidator(final Map<IModFile.Type, List<ModFile>> modFiles, final List<IModFileInfo> brokenFiles, final List<EarlyLoadingException.ExceptionData> discoveryErrorData) {
this.modFiles = modFiles;
this.candidateMods = lst(modFiles.get(IModFile.Type.MOD));
this.candidateMods.addAll(lst(modFiles.get(IModFile.Type.GAMELIBRARY)));
this.gameLibraries = lst(modFiles.get(IModFile.Type.GAMELIBRARY));
this.candidateMods.addAll(this.gameLibraries);
this.candidatePlugins = lst(modFiles.get(IModFile.Type.LANGPROVIDER));
this.candidatePlugins.addAll(lst(modFiles.get(IModFile.Type.LIBRARY)));
this.discoveryErrorData = discoveryErrorData;
@@ -55,8 +59,7 @@ public class ModValidator {
@NotNull
private List<ModFile> validateFiles(final List<ModFile> mods) {
final List<ModFile> brokenFiles = new ArrayList<>();
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext(); )
{
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext();) {
ModFile modFile = iterator.next();
if (!modFile.getProvider().isValid(modFile) || !modFile.identifyMods()) {
LOGGER.warn(LogMarkers.SCAN, "File {} has been ignored - it is invalid", modFile.getFilePath());
@@ -72,7 +75,26 @@ public class ModValidator {
}
public ITransformationService.Resource getModResources() {
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, this.candidateMods.stream().map(IModFile::getSecureJar).toList());
var mods = new ArrayList<SecureJar>();
// Add only the valid mods that we will be attempting to load.
// If any detectable error happens during the sorting process {missing deps, duplicates,
// This helps prevent coremods/mixins from screwing up us displaying the error screens that the sorting/validation is trying to display.
// This won't fix them all as they are still loaded and will still apply but it might help
for (var info : this.loadingModList.getModFiles())
mods.add(info.getFile().getSecureJar());
// Add any game libraries, this *may* be duplicates, depending on the state of the sorting. But until I get around to re-writing
// that clusterfuck of a system, have this simple de-duplication. Order of resource is important, but i'm unsure if duplication is
// so might as well waste a few cycles on checking. Still faster then converting from a set to a list.
// Ideally we would explicitly list out which mods to load {forge and MC being the only ones} but some coremods could require extra things.
// So try game libraries as well
for (var lib : this.gameLibraries) {
var jar = lib.getSecureJar();
if (!mods.contains(jar))
mods.add(jar);
}
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, mods);
}
private List<EarlyLoadingException.ExceptionData> validateLanguages() {
@@ -45,7 +45,7 @@ public class Scanner {
try (InputStream in = Files.newInputStream(path)){
ModClassVisitor mcv = new ModClassVisitor();
ClassReader cr = new ClassReader(in);
cr.accept(mcv, 0);
cr.accept(mcv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
mcv.buildData(result.getClasses(), result.getAnnotations());
} catch (IOException | IllegalArgumentException e) {
// mark path bad
@@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public final class ProgressMeter {
private final String name;
private final int steps;
private AtomicInteger current;
private final AtomicInteger current;
private Message label;
public ProgressMeter(String name, int steps, int current, Message label) {
@@ -0,0 +1,18 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.api.distmarker.Dist;
public class FMLClientDevLaunchHandler extends CommonDevLaunchHandler {
@Override public String name() { return "fmlclientdev"; }
@Override public Dist getDist() { return Dist.CLIENT; }
@Override
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
clientService(arguments, layer);
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
import net.minecraftforge.fml.loading.LibraryFinder;
import net.minecraftforge.fml.loading.VersionInfo;
public class FMLClientLaunchHandler extends CommonClientLaunchHandler {
@Override public String name() { return "fmlclient"; }
@Override
protected void processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods) {
var fmlonly = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "fmlonly", "", "universal", versionInfo.mcAndForgeVersion());
mods.add(List.of(fmlonly));
}
}
@@ -0,0 +1,21 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.api.distmarker.Dist;
public class FMLClientUserdevLaunchHandler extends FMLUserdevLaunchHandler {
@Override
public String name() { return "fmlclientuserdev"; }
@Override
public Dist getDist() { return Dist.CLIENT; }
@Override
protected void devService(String[] arguments, ModuleLayer layer) throws Throwable {
clientService(arguments, layer);
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.api.distmarker.Dist;
public class FMLDataUserdevLaunchHandler extends FMLUserdevLaunchHandler {
@Override
public String name() { return "fmldatauserdev"; }
@Override
public Dist getDist() { return Dist.CLIENT; }
@Override
public boolean isData() { return true; }
@Override
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
dataService(arguments, layer);
}
}
@@ -0,0 +1,18 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.api.distmarker.Dist;
public class FMLServerDevLaunchHandler extends CommonDevLaunchHandler {
@Override public String name() { return "fmlserverdev"; }
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
@Override
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
serverService(arguments, layer);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import cpw.mods.modlauncher.api.ILaunchHandlerService;
import net.minecraftforge.fml.loading.LibraryFinder;
import net.minecraftforge.fml.loading.VersionInfo;
import java.nio.file.Path;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Stream;
public class FMLServerLaunchHandler extends CommonServerLaunchHandler implements ILaunchHandlerService {
@Override public String name() { return "fmlserver"; }
@Override
protected BiPredicate<String, String> processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, BiPredicate<String, String> filter, Stream.Builder<List<Path>> mods) {
var fmlonly = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "fmlonly", "", "universal", versionInfo.mcAndForgeVersion());
mods.add(List.of(fmlonly));
return filter;
}
}
@@ -0,0 +1,18 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.api.distmarker.Dist;
public class FMLServerUserdevLaunchHandler extends FMLUserdevLaunchHandler {
@Override public String name() { return "fmlserveruserdev"; }
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
@Override
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
serverService(arguments, layer);
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.fml.loading.VersionInfo;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
public abstract class FMLUserdevLaunchHandler extends CommonUserdevLaunchHandler {
@Override
protected void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods) {
var fmlonly = findJarOnClasspath(classpath, "fmlonly-" + versionInfo.mcAndForgeVersion());
mc.add(fmlonly);
}
}
@@ -1,3 +1,11 @@
net.minecraftforge.fml.loading.targets.FMLClientLaunchHandler
net.minecraftforge.fml.loading.targets.FMLClientDevLaunchHandler
net.minecraftforge.fml.loading.targets.FMLClientUserdevLaunchHandler
net.minecraftforge.fml.loading.targets.FMLServerLaunchHandler
net.minecraftforge.fml.loading.targets.FMLServerDevLaunchHandler
net.minecraftforge.fml.loading.targets.FMLServerUserdevLaunchHandler
net.minecraftforge.fml.loading.targets.FMLDataUserdevLaunchHandler
net.minecraftforge.fml.loading.targets.ForgeClientLaunchHandler
net.minecraftforge.fml.loading.targets.ForgeClientDevLaunchHandler
net.minecraftforge.fml.loading.targets.ForgeClientUserdevLaunchHandler
+1
View File
@@ -0,0 +1 @@
../../src/fmlcommon/
@@ -0,0 +1,47 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fmlonly;
import net.minecraftforge.eventbus.api.BusBuilder;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.I18NParser;
import net.minecraftforge.fml.IBindingsProvider;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class FMLOnlyBindings implements IBindingsProvider {
private static final IEventBus DUMMYFORGEBUS = BusBuilder.builder().build();
@Override
public Supplier<IEventBus> getForgeBusSupplier() {
return ()->DUMMYFORGEBUS;
}
@Override
public Supplier<I18NParser> getMessageParser() {
return ()->new I18NParser() {
@Override
public String parseMessage(final String i18nMessage, final Object... args) {
return i18nMessage + Arrays.stream(args).map(Objects::toString).collect(Collectors.joining(",", "[", "]"));
}
@Override
public String stripControlCodes(final String toStrip) {
return toStrip;
}
};
}
@Override
public Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration() {
return ()->new IConfigEvent.ConfigConfig(ModConfigEvent.Loading::new, ModConfigEvent.Reloading::new, ModConfigEvent.Unloading::new);
}
}
@@ -0,0 +1,11 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fmlonly;
import net.minecraftforge.fml.common.Mod;
@Mod("fmlonly")
public class FMLOnlyMod {}
@@ -0,0 +1,81 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fmlonlyclient;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.ClientPackSource;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.LoadingFailedException;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModWorkManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@OnlyIn(Dist.CLIENT)
public class ClientModLoader
{
private static boolean loading;
private static Minecraft mc;
private static boolean loadingComplete;
private static LoadingFailedException error;
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager)
{
// force log4j to shutdown logging in a shutdown hook. This is because we disable default shutdown hook so the server properly logs it's shutdown
Runtime.getRuntime().addShutdownHook(new Thread(LogManager::shutdown));
loading = true;
ClientModLoader.mc = minecraft;
createRunnableWithCatch(()->ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{})).run();
mcResourceManager.registerReloadListener(ClientModLoader::onResourceReload);
}
private static CompletableFuture<Void> onResourceReload(final PreparableReloadListener.PreparationBarrier stage, final ResourceManager resourceManager, final ProfilerFiller prepareProfiler, final ProfilerFiller executeProfiler, final Executor asyncExecutor, final Executor syncExecutor) {
return CompletableFuture.runAsync(createRunnableWithCatch(() -> startModLoading(ModWorkManager.wrappedExecutor(syncExecutor), asyncExecutor)), ModWorkManager.parallelExecutor())
.thenCompose(stage::wait)
.thenRunAsync(() -> finishModLoading(ModWorkManager.wrappedExecutor(syncExecutor), asyncExecutor), ModWorkManager.parallelExecutor());
}
private static Runnable createRunnableWithCatch(Runnable r) {
return ()-> {
if (loadingComplete) return;
try {
r.run();
} catch (LoadingFailedException e) {
if (error == null) error = e;
}
};
}
private static void startModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor) {
if (error!=null) throw error;
createRunnableWithCatch(() -> ModLoader.get().loadMods(syncExecutor, parallelExecutor, ()->{})).run();
}
private static void finishModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor)
{
if (error!=null) throw error;
createRunnableWithCatch(() -> ModLoader.get().finishMods(syncExecutor, parallelExecutor, ()->{})).run();
loading = false;
loadingComplete = true;
// reload game settings on main thread
syncExecutor.execute(()->mc.options.load());
}
public static boolean isLoading()
{
return loading;
}
}
@@ -0,0 +1,56 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fmlonlyserver;
import joptsimple.OptionParser;
import net.minecraftforge.fml.LoadingFailedException;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingWarning;
import net.minecraftforge.fml.ModWorkManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.util.List;
import static net.minecraftforge.fml.Logging.LOADING;
public class ServerModLoader
{
private static final Logger LOGGER = LogManager.getLogger();
private static boolean hasErrors = false;
public static void addOptions(OptionParser parser)
{
// We consume this argument as we use it in the launcher and the client side.
parser.accepts("gameDir").withRequiredArg().ofType(File.class).defaultsTo(new File("."));
}
public static void load()
{
try
{
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().loadMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().finishMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
} catch (LoadingFailedException error)
{
ServerModLoader.hasErrors = true;
throw error;
}
List<ModLoadingWarning> warnings = ModLoader.get().getWarnings();
if (!warnings.isEmpty())
{
LOGGER.warn(LOADING, "Mods loaded with {} warnings", warnings.size());
warnings.forEach(warning -> LOGGER.warn(LOADING, warning.formatToString()));
}
}
public static boolean hasErrors()
{
return ServerModLoader.hasErrors;
}
}
@@ -0,0 +1,4 @@
{
"load_fml_client": "coremods/load_fml_client.js",
"load_fml_server": "coremods/load_fml_server.js"
}
@@ -0,0 +1,16 @@
modLoader="javafml"
loaderVersion="[24,]"
issueTrackerURL="https://www.minecraftforge.net/"
license="LGPL v2.1"
[[mods]]
modId="fmlonly"
# We use the global forge version
version="${global.forgeVersion}"
updateJSONURL="https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"
displayName="Forge"
credits="Anyone who has contributed on Github and supports our development"
authors="LexManos,cpw"
description='''
Forge, a broad compatibility API.
'''
@@ -0,0 +1 @@
net.minecraftforge.fmlonly.FMLOnlyBindings
@@ -0,0 +1 @@
net.minecraftforge.fml.core.ModStateProvider
@@ -0,0 +1,36 @@
var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI')
var Opcodes = Java.type('org.objectweb.asm.Opcodes')
function initializeCoreMod() {
return {
'minecraft': {
'target': {
'type': 'METHOD',
'class': 'net.minecraft.client.Minecraft',
'methodName': '<init>',
'methodDesc': '(Lnet/minecraft/client/main/GameConfig;)V'
},
'transformer': function(methodNode) {
//print(ASMAPI.methodNodeToString(methodNode))
var meth = ASMAPI.getMethodNode();
var resourcePackRepository = ASMAPI.mapField("f_91038_")
var resourceManager = ASMAPI.mapField("f_91036_")
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/client/Minecraft", resourcePackRepository, "Lnet/minecraft/server/packs/repository/PackRepository;");
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/client/Minecraft", resourceManager, "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;");
meth.visitMethodInsn(Opcodes.INVOKESTATIC, "net/minecraftforge/fmlonlyclient/ClientModLoader", "begin", "(Lnet/minecraft/client/Minecraft;Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/server/packs/resources/ReloadableResourceManager;)V", false)
for (var i=0; i<methodNode.instructions.size(); i++) {
var ain = methodNode.instructions.get(i);
if (ain.getOpcode() == Opcodes.PUTFIELD && ain.name.equals(resourceManager)) {
methodNode.instructions.insert(ain, meth.instructions);
break;
}
}
return methodNode;
}
},
}
}
@@ -0,0 +1,35 @@
var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI')
var Opcodes = Java.type('org.objectweb.asm.Opcodes')
function initializeCoreMod() {
return {
'minecraft': {
'target': {
'type': 'METHOD',
'class': 'net.minecraft.server.Main',
'methodName': 'main',
'methodDesc': '([Ljava/lang/String;)V'
},
'transformer': function(methodNode) {
var meth = ASMAPI.getMethodNode();
meth.visitMethodInsn(Opcodes.INVOKESTATIC, 'net/minecraftforge/fmlonlyserver/ServerModLoader', 'load', '()V', false)
var methOptions = ASMAPI.getMethodNode();
methOptions.visitIntInsn(Opcodes.ALOAD, 1);
methOptions.visitMethodInsn(Opcodes.INVOKESTATIC, 'net/minecraftforge/fmlonlyserver/ServerModLoader', 'addOptions', '(Ljoptsimple/OptionParser;)V', false)
for (var i=0; i<methodNode.instructions.size(); i++) {
var ain = methodNode.instructions.get(i);
if (ain.getOpcode() == Opcodes.INVOKESPECIAL && ain.owner == 'joptsimple/OptionParser' && ain.name == '<init>' && ain.desc == '()V') {
// Inject after the STORE
methodNode.instructions.insert(methodNode.instructions.get(i + 1), methOptions.instructions);
} else if (ain.getOpcode() == Opcodes.INVOKESTATIC && ain.owner == 'net/minecraft/Util' && ain.name == ASMAPI.mapMethod('m_137584_') /* startTimerHackThread */ && ain.desc == '()V') {
methodNode.instructions.insert(ain, meth.instructions);
break; // By this point we've already reached the first injection point so break
}
}
return methodNode;
}
},
}
}
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+6 -5
View File
@@ -85,9 +85,6 @@ done
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
@@ -8,7 +8,7 @@ package net.minecraftforge.fml.javafmlmod;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
public class FMLJavaModLoadingContext
public class FMLJavaModLoadingContext extends ModLoadingContext
{
private final FMLModContainer container;
@@ -24,11 +24,18 @@ public class FMLJavaModLoadingContext
return container.getEventBus();
}
@Override
public FMLModContainer getContainer() {
return container;
}
/**
* Helper to get the right instance from the {@link ModLoadingContext} correctly.
* @return The FMLJavaMod language specific extension from the ModLoadingContext
*
* @deprecated use {@link FMLJavaModLoadingContext} in your mod constructor
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public static FMLJavaModLoadingContext get() {
return ModLoadingContext.get().extension();
}
@@ -21,6 +21,9 @@ import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.Optional;
public class FMLModContainer extends ModContainer
@@ -31,6 +34,7 @@ public class FMLModContainer extends ModContainer
private final IEventBus eventBus;
private Object modInstance;
private final Class<?> modClass;
private final FMLJavaModLoadingContext context = new FMLJavaModLoadingContext(this);
public FMLModContainer(IModInfo info, String className, ModFileScanData modFileScanResults, ModuleLayer gameLayer)
{
@@ -40,8 +44,7 @@ public class FMLModContainer extends ModContainer
activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod);
this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build();
this.configHandler = Optional.of(ce->this.eventBus.post(ce.self()));
final FMLJavaModLoadingContext contextExtension = new FMLJavaModLoadingContext(this);
this.contextExtension = () -> contextExtension;
this.contextExtension = () -> context;
try
{
var layer = gameLayer.findModule(info.getOwningFile().moduleName()).orElseThrow();
@@ -65,11 +68,22 @@ public class FMLModContainer extends ModContainer
try
{
LOGGER.trace(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.getName());
this.modInstance = modClass.getDeclaredConstructor().newInstance();
Constructor<?> constructor;
try {
constructor = modClass.getDeclaredConstructor(context.getClass());
} catch (NoSuchMethodException | SecurityException exception) {
constructor = modClass.getDeclaredConstructor();
}
this.modInstance = constructor.getParameterCount() == 0 ? constructor.newInstance() : constructor.newInstance(context);
LOGGER.trace(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
}
catch (Throwable e)
{
// When a mod constructor throws an exception, it's wrapped in an InvocationTargetException which hides the
// actual exception from the mod loading error screen.
if (e instanceof InvocationTargetException wrapped)
e = Objects.requireNonNullElse(wrapped.getCause(), e); // unwrap the exception
LOGGER.error(LOADING,"Failed to create mod instance. ModID: {}, class {}", getModId(), modClass.getName(), e);
throw new ModLoadingException(modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, modClass);
}
+7 -7
View File
@@ -16,19 +16,19 @@ Step 1: Open your command-line and browse to the folder where you extracted the
Step 2: You're left with a choice.
If you prefer to use Eclipse:
1. Run the following command: `gradlew genEclipseRuns` (`./gradlew genEclipseRuns` if you are on Mac/Linux)
1. Run the following command: `./gradlew genEclipseRuns`
2. Open Eclipse, Import > Existing Gradle Project > Select Folder
or run `gradlew eclipse` to generate the project.
If you prefer to use IntelliJ:
1. Open IDEA, and import project.
2. Select your build.gradle file and have it import.
3. Run the following command: `gradlew genIntellijRuns` (`./gradlew genIntellijRuns` if you are on Mac/Linux)
3. Run the following command: `./gradlew genIntellijRuns`
4. Refresh the Gradle Project in IDEA if required.
If at any point you are missing libraries in your IDE, or you've run into problems you can
run `gradlew --refresh-dependencies` to refresh the local cache. `gradlew clean` to reset everything
{this does not affect your code} and then start the process again.
(this does not affect your code) and then start the process again.
Mapping Names:
=============================
@@ -40,7 +40,7 @@ https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
Additional Resources:
=========================
Community Documentation: https://mcforge.readthedocs.io/en/latest/gettingstarted/
LexManos' Install Video: https://www.youtube.com/watch?v=8VEdtQLuLO0
Forge Forum: https://forums.minecraftforge.net/
Forge Discord: https://discord.gg/UvedJ9m
Community Documentation: https://docs.minecraftforge.net/en/1.20.1/gettingstarted/
LexManos' Install Video: https://youtu.be/8VEdtQLuLO0
Forge Forums: https://forums.minecraftforge.net/
Forge Discord: https://discord.minecraftforge.net/
+1 -1
View File
@@ -9,5 +9,5 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
@@ -18,7 +18,6 @@ import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@@ -61,9 +60,9 @@ public class ExampleMod
output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event
}).build());
public ExampleMod()
public ExampleMod(FMLJavaModLoadingContext context)
{
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
IEventBus modEventBus = context.getModEventBus();
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
@@ -82,7 +81,7 @@ public class ExampleMod
modEventBus.addListener(this::addCreative);
// Register our mod's ForgeConfigSpec so that Forge can create and load the config file for us
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);
context.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
}
private void commonSetup(final FMLCommonSetupEvent event)
+5 -2
View File
@@ -12,6 +12,9 @@ loaderVersion="${loader_version_range}" #mandatory This is typically bumped ever
license="${mod_license}"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or Open to LAN),
# set this to true, and Forge will set the correct displayTest for you and skip loading your mod on dedicated servers.
#clientSideOnly=true #optional - defaults to false if absent
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
@@ -36,7 +39,7 @@ authors="${mod_authors}" #optional
# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component.
# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value.
# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself.
#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional)
#displayTest="MATCH_VERSION" # if nothing is specified, MATCH_VERSION is the default when clientSideOnly=false, otherwise IGNORE_ALL_VERSION when clientSideOnly=true (#optional)
# The description text for the mod (multi line!) (#mandatory)
description='''${mod_description}'''
@@ -67,4 +70,4 @@ description='''${mod_description}'''
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
# stop your mod loading on the server for example.
#[features.${mod_id}]
#openGLVersion="[3.2,)"
#openGLVersion="[3.2,)"
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/platform/Window.java
+++ b/com/mojang/blaze3d/platform/Window.java
@@ -81,7 +_,8 @@
@@ -83,7 +_,8 @@
GLFW.glfwWindowHint(139267, 2);
GLFW.glfwWindowHint(139272, 204801);
GLFW.glfwWindowHint(139270, 1);
@@ -10,15 +10,15 @@
if (monitor != null) {
VideoMode videomode = monitor.m_84948_(this.f_85355_ ? this.f_85354_ : Optional.empty());
this.f_85350_ = this.f_85357_ = monitor.m_84951_() + videomode.m_85332_() / 2 - this.f_85359_ / 2;
@@ -93,6 +_,7 @@
@@ -95,6 +_,7 @@
this.f_85350_ = this.f_85357_ = aint1[0];
this.f_85351_ = this.f_85358_ = aint[0];
}
+ }
GLFW.glfwMakeContextCurrent(this.f_85349_);
GL.createCapabilities();
@@ -242,6 +_,7 @@
Locale locale = Locale.getDefault(Category.FORMAT);
@@ -238,6 +_,7 @@
GLFW.glfwGetFramebufferSize(this.f_85349_, aint, aint1);
this.f_85361_ = aint[0] > 0 ? aint[0] : 1;
this.f_85362_ = aint1[0] > 0 ? aint1[0] : 1;
@@ -1,6 +1,6 @@
--- a/com/mojang/math/Transformation.java
+++ b/com/mojang/math/Transformation.java
@@ -13,7 +_,7 @@
@@ -14,7 +_,7 @@
import org.joml.Vector3f;
import org.joml.Vector3fc;
@@ -9,7 +9,7 @@
private final Matrix4f f_121078_;
public static final Codec<Transformation> f_268453_ = RecordCodecBuilder.create((p_269604_) -> {
return p_269604_.group(ExtraCodecs.f_252432_.fieldOf("translation").forGetter((p_269599_) -> {
@@ -156,6 +_,19 @@
@@ -163,6 +_,19 @@
public int hashCode() {
return Objects.hash(this.f_121078_);
}
@@ -1,6 +1,6 @@
--- a/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
+++ b/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
@@ -61,6 +_,15 @@
@@ -68,6 +_,15 @@
return Component.m_237119_().m_7220_(this.f_200947_.f_287789_).m_130946_(": ").m_7220_(this.f_200947_.f_287787_);
}
@@ -14,5 +14,5 @@
+ }
+
public void m_88315_(GuiGraphics p_283497_, int p_88680_, int p_88681_, float p_88682_) {
super.m_88315_(p_283497_, p_88680_, p_88681_, p_88682_);
p_283497_.m_280653_(this.f_96547_, this.f_200947_.f_287789_, this.f_96543_ / 2, 80, -1);
this.m_280273_(p_283497_);
p_283497_.m_280653_(this.f_96547_, this.f_200947_.f_287789_, this.f_96543_ / 2, 80, 16777215);
@@ -0,0 +1,15 @@
--- a/com/mojang/realmsclient/gui/screens/RealmsNotificationsScreen.java
+++ b/com/mojang/realmsclient/gui/screens/RealmsNotificationsScreen.java
@@ -45,9 +_,9 @@
}
};
private final RealmsNotificationsScreen.DataFetcherConfiguration f_273849_ = new RealmsNotificationsScreen.DataFetcherConfiguration() {
- public DataFetcher.Subscription m_274316_(RealmsDataFetcher p_275731_) {
- DataFetcher.Subscription datafetcher$subscription = p_275731_.f_238549_.m_239139_();
- RealmsNotificationsScreen.this.m_274585_(p_275731_, datafetcher$subscription);
+ public DataFetcher.Subscription m_274316_(RealmsDataFetcher p_275318_) {
+ DataFetcher.Subscription datafetcher$subscription = p_275318_.f_238549_.m_239139_();
+ RealmsNotificationsScreen.this.m_274585_(p_275318_, datafetcher$subscription);
return datafetcher$subscription;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/CrashReport.java
+++ b/net/minecraft/CrashReport.java
@@ -57,14 +_,8 @@
@@ -57,14 +_,9 @@
if (this.f_127506_ != null && this.f_127506_.length > 0) {
p_127520_.append("-- Head --\n");
p_127520_.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
@@ -12,6 +12,7 @@
- }
-
- p_127520_.append("\n");
+ p_127520_.append(net.minecraftforge.logging.CrashReportAnalyser.appendSuspectedMods(this.f_127501_, this.f_127506_));
+ p_127520_.append("Stacktrace:");
+ p_127520_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.f_127506_));
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/SharedConstants.java
+++ b/net/minecraft/SharedConstants.java
@@ -212,6 +_,7 @@
@@ -210,6 +_,7 @@
}
static {
@@ -1,6 +1,6 @@
--- a/net/minecraft/Util.java
+++ b/net/minecraft/Util.java
@@ -172,6 +_,11 @@
@@ -171,6 +_,11 @@
return 255;
}
@@ -12,7 +12,7 @@
public static ExecutorService m_183991_() {
return f_137444_;
}
@@ -240,7 +_,7 @@
@@ -239,7 +_,7 @@
try {
type = DataFixers.m_14512_().getSchema(DataFixUtils.makeKey(SharedConstants.m_183709_().m_183476_().m_193006_())).getChoiceType(p_137552_, p_137553_);
} catch (IllegalArgumentException illegalargumentexception) {
@@ -1,17 +1,26 @@
--- a/net/minecraft/advancements/Advancement.java
+++ b/net/minecraft/advancements/Advancement.java
@@ -62,7 +_,14 @@
return jsonobject;
@@ -150,7 +_,7 @@
return this.f_138305_;
}
+ /** @deprecated Forge: use {@linkplain #fromJson(JsonObject, DeserializationContext, net.minecraftforge.common.crafting.conditions.ICondition.IContext) overload with context}. */
+ @Deprecated
public static Advancement m_294730_(JsonObject p_300691_, DeserializationContext p_300053_) {
+ return fromJson(p_300691_, p_300053_, net.minecraftforge.common.crafting.conditions.ICondition.IContext.EMPTY);
+ }
- public static class Builder {
+ public static class Builder implements net.minecraftforge.common.extensions.IForgeAdvancementBuilder {
@Nullable
private ResourceLocation f_138332_;
@Nullable
@@ -340,7 +_,14 @@
return "Task Advancement{parentId=" + this.f_138332_ + ", display=" + this.f_138334_ + ", rewards=" + this.f_138335_ + ", criteria=" + this.f_138336_ + ", requirements=" + Arrays.deepToString(this.f_138337_) + ", sends_telemetry_event=" + this.f_285655_ + "}";
}
+ /** @deprecated Forge: use {@linkplain #fromJson(JsonObject, DeserializationContext, net.minecraftforge.common.crafting.conditions.ICondition.IContext) overload with context}. */
+ @Deprecated
public static Advancement.Builder m_138380_(JsonObject p_138381_, DeserializationContext p_138382_) {
+ return fromJson(p_138381_, p_138382_, net.minecraftforge.common.crafting.conditions.ICondition.IContext.EMPTY);
+ }
+
+ public static Advancement fromJson(JsonObject p_300691_, DeserializationContext p_300053_, net.minecraftforge.common.crafting.conditions.ICondition.IContext context) {
+ //if ((p_300691_ = net.minecraftforge.common.crafting.ConditionalAdvancement.processConditional(p_300691_, context)) == null) return null;
Optional<ResourceLocation> optional = p_300691_.has("parent") ? Optional.of(new ResourceLocation(GsonHelper.m_13906_(p_300691_, "parent"))) : Optional.empty();
Optional<DisplayInfo> optional1 = p_300691_.has("display") ? Optional.of(DisplayInfo.m_14981_(GsonHelper.m_13930_(p_300691_, "display"))) : Optional.empty();
AdvancementRewards advancementrewards = p_300691_.has("rewards") ? AdvancementRewards.m_9991_(GsonHelper.m_13930_(p_300691_, "rewards")) : AdvancementRewards.f_9978_;
+ public static Advancement.Builder fromJson(JsonObject p_138381_, DeserializationContext p_138382_, net.minecraftforge.common.crafting.conditions.ICondition.IContext context) {
+ if ((p_138381_ = net.minecraftforge.common.crafting.ConditionalAdvancement.processConditional(p_138381_, context)) == null) return null;
ResourceLocation resourcelocation = p_138381_.has("parent") ? new ResourceLocation(GsonHelper.m_13906_(p_138381_, "parent")) : null;
DisplayInfo displayinfo = p_138381_.has("display") ? DisplayInfo.m_14981_(GsonHelper.m_13930_(p_138381_, "display")) : null;
AdvancementRewards advancementrewards = p_138381_.has("rewards") ? AdvancementRewards.m_9991_(GsonHelper.m_13930_(p_138381_, "rewards")) : AdvancementRewards.f_9978_;
@@ -1,11 +1,47 @@
--- a/net/minecraft/advancements/critereon/ItemPredicate.java
+++ b/net/minecraft/advancements/critereon/ItemPredicate.java
@@ -50,7 +_,7 @@
@@ -29,6 +_,8 @@
import net.minecraft.world.level.ItemLike;
public class ItemPredicate {
+ private static final Map<ResourceLocation, java.util.function.Function<JsonObject, ItemPredicate>> custom_predicates = new java.util.HashMap<>();
+ private static final Map<ResourceLocation, java.util.function.Function<JsonObject, ItemPredicate>> unmod_predicates = java.util.Collections.unmodifiableMap(custom_predicates);
public static final ItemPredicate f_45028_ = new ItemPredicate();
@Nullable
private final TagKey<Item> f_45029_;
@@ -81,7 +_,7 @@
return false;
} else {
if (!this.f_45033_.isEmpty()) {
if (this.f_45033_.length > 0) {
- Map<Enchantment, Integer> map = EnchantmentHelper.m_44882_(p_45050_.m_41785_());
+ Map<Enchantment, Integer> map = p_45050_.getAllEnchantments();
for(EnchantmentPredicate enchantmentpredicate : this.f_45033_) {
if (!enchantmentpredicate.m_30476_(map)) {
@@ -108,6 +_,11 @@
public static ItemPredicate m_45051_(@Nullable JsonElement p_45052_) {
if (p_45052_ != null && !p_45052_.isJsonNull()) {
JsonObject jsonobject = GsonHelper.m_13918_(p_45052_, "item");
+ if (jsonobject.has("type")) {
+ final ResourceLocation rl = new ResourceLocation(GsonHelper.m_13906_(jsonobject, "type"));
+ if (custom_predicates.containsKey(rl)) return custom_predicates.get(rl).apply(jsonobject);
+ else throw new JsonSyntaxException("There is no ItemPredicate of type "+rl);
+ }
MinMaxBounds.Ints minmaxbounds$ints = MinMaxBounds.Ints.m_55373_(jsonobject.get("count"));
MinMaxBounds.Ints minmaxbounds$ints1 = MinMaxBounds.Ints.m_55373_(jsonobject.get("durability"));
if (jsonobject.has("data")) {
@@ -215,6 +_,14 @@
} else {
return new ItemPredicate[0];
}
+ }
+
+ public static void register(ResourceLocation name, java.util.function.Function<JsonObject, ItemPredicate> deserializer) {
+ custom_predicates.put(name, deserializer);
+ }
+
+ public static Map<ResourceLocation, java.util.function.Function<JsonObject, ItemPredicate>> getPredicates() {
+ return unmod_predicates;
}
public static class Builder {
@@ -1,20 +1,20 @@
--- a/net/minecraft/client/ClientRecipeBook.java
+++ b/net/minecraft/client/ClientRecipeBook.java
@@ -56,7 +_,7 @@
Recipe<?> recipe = recipeholder.f_291008_();
@@ -54,7 +_,7 @@
for(Recipe<?> recipe : p_90643_) {
if (!recipe.m_5598_() && !recipe.m_142505_()) {
RecipeBookCategories recipebookcategories = m_90646_(recipeholder);
RecipeBookCategories recipebookcategories = m_90646_(recipe);
- String s = recipe.m_6076_();
+ String s = recipe.m_6076_().isEmpty() ? recipeholder.f_291676_().toString() : recipe.m_6076_(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
+ String s = recipe.m_6076_().isEmpty() ? recipe.m_6423_().toString() : recipe.m_6076_(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
if (s.isEmpty()) {
map.computeIfAbsent(recipebookcategories, (p_90645_) -> {
return Lists.newArrayList();
@@ -144,6 +_,8 @@
@@ -141,6 +_,8 @@
} else if (recipetype == RecipeType.f_44113_) {
return RecipeBookCategories.SMITHING;
} else {
+ RecipeBookCategories categories = net.minecraftforge.client.RecipeBookManager.findCategories((RecipeType) recipetype, p_299041_);
+ RecipeBookCategories categories = net.minecraftforge.client.RecipeBookManager.findCategories((RecipeType) recipetype, p_90647_);
+ if (categories != null) return categories;
f_90618_.warn("Unknown recipe category: {}/{}", LogUtils.defer(() -> {
return BuiltInRegistries.f_256990_.m_7981_(recipe.m_6671_());
}), LogUtils.defer(p_299041_::f_291676_));
return BuiltInRegistries.f_256990_.m_7981_(p_90647_.m_6671_());
}), LogUtils.defer(p_90647_::m_6423_));
@@ -90,12 +90,12 @@
}
public String m_90865_() {
@@ -184,4 +_,84 @@
@@ -183,5 +_,88 @@
public void m_7249_(boolean p_90846_) {
this.f_90817_ = p_90846_;
}
+ }
+
+ /****************** Forge Start *****************************/
+ private net.minecraftforge.client.settings.KeyModifier keyModifierDefault = net.minecraftforge.client.settings.KeyModifier.NONE;
+ private net.minecraftforge.client.settings.KeyModifier keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
+ private net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext = net.minecraftforge.client.settings.KeyConflictContext.UNIVERSAL;
@@ -165,13 +165,17 @@
+ }
+
+ @Override
+ public void setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode) {
+ this.f_90816_ = keyCode;
+ if (keyModifier.matches(keyCode))
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
+ public void setKeyModifierAndCode(@org.jetbrains.annotations.Nullable net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode) {
+ f_90810_.remove(this);
+
+ if (keyModifier == null)
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.getModifier(this.f_90816_);
+ if (keyModifier == null || keyCode == InputConstants.f_84822_ || net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(keyCode))
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
+
+ this.f_90816_ = keyCode;
+ this.keyModifier = keyModifier;
+
+ f_90810_.put(keyCode, this);
+ }
+ /****************** Forge End *****************************/
}
}
@@ -1,26 +1,6 @@
--- a/net/minecraft/client/KeyboardHandler.java
+++ b/net/minecraft/client/KeyboardHandler.java
@@ -340,7 +_,9 @@
}
}
- if (p_90897_ == 1 && (!(this.f_90867_.f_91080_ instanceof KeyBindsScreen) || ((KeyBindsScreen)screen).f_193976_ <= Util.m_137550_() - 20L)) {
+
+ if ((!(this.f_90867_.f_91080_ instanceof KeyBindsScreen) || ((KeyBindsScreen)screen).f_193976_ <= Util.m_137550_() - 20L)) {
+ if (p_90897_ == 1) {
if (this.f_90867_.f_91066_.f_92105_.m_90832_(p_90895_, p_90896_)) {
this.f_90867_.m_91268_().m_85438_();
this.f_90867_.f_91066_.m_231829_().m_231514_(this.f_90867_.m_91268_().m_85440_());
@@ -358,6 +_,8 @@
});
return;
}
+ } else if (p_90897_ == 0 /*GLFW_RELEASE*/ && this.f_90867_.f_91080_ instanceof KeyBindsScreen)
+ ((KeyBindsScreen)this.f_90867_.f_91080_).f_193975_ = null; //Forge: Unset pure modifiers.
}
if (this.f_90867_.m_240477_().m_93316_() && this.f_90867_.f_91066_.m_292959_().m_231551_()) {
@@ -380,11 +_,15 @@
@@ -369,11 +_,15 @@
Screen.m_96579_(() -> {
if (p_90897_ != 1 && p_90897_ != 2) {
if (p_90897_ == 0) {
@@ -38,8 +18,8 @@
}
}, "keyPressed event handler", screen.getClass().getCanonicalName());
@@ -443,22 +_,26 @@
this.f_90867_.m_91111_(p_90895_ - 48);
@@ -424,22 +_,26 @@
}
}
}
-
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Minecraft.java
+++ b/net/minecraft/client/Minecraft.java
@@ -251,7 +_,7 @@
@@ -249,7 +_,7 @@
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
@@ -9,15 +9,15 @@
static Minecraft f_90981_;
private static final Logger f_90982_ = LogUtils.getLogger();
public static final boolean f_91002_ = Util.m_137581_() == Util.OS.OSX;
@@ -421,7 +_,6 @@
}, Util.m_183992_());
@@ -413,7 +_,6 @@
this.f_193584_ = this.m_193585_(this.f_231338_, p_91084_);
this.f_90998_ = p_91084_.f_101905_.f_101942_;
f_90982_.info("Setting user: {}", (Object)this.f_90998_.m_92546_());
- f_90982_.debug("(Session ID is {})", (Object)this.f_90998_.m_92544_());
this.f_91033_ = p_91084_.f_101908_.f_101926_;
this.f_91034_ = !p_91084_.f_101908_.f_101929_;
this.f_91035_ = !p_91084_.f_101908_.f_101930_;
@@ -457,15 +_,15 @@
@@ -449,15 +_,15 @@
}
this.f_90990_.m_85380_(this.f_91066_.m_232035_().m_231551_());
@@ -35,7 +35,7 @@
this.f_91038_.m_10506_();
this.f_91066_.m_92145_(this.f_91038_);
this.f_91039_ = new LanguageManager(this.f_91066_.f_92075_);
@@ -511,10 +_,13 @@
@@ -504,10 +_,13 @@
this.f_91063_ = new GameRenderer(this, this.f_90994_.m_234586_(), this.f_91036_, this.f_90993_);
this.f_91036_.m_7217_(this.f_91063_.m_247116_());
this.f_91060_ = new LevelRenderer(this, this.f_90994_, this.f_167845_, this.f_90993_);
@@ -50,7 +50,7 @@
this.f_91036_.m_7217_(this.f_91061_);
this.f_91053_ = new PaintingTextureManager(this.f_90987_);
this.f_91036_.m_7217_(this.f_91053_);
@@ -525,7 +_,10 @@
@@ -516,7 +_,10 @@
this.f_91047_ = new GpuWarnlistManager();
this.f_91036_.m_7217_(this.f_91047_);
this.f_91036_.m_7217_(this.f_205120_);
@@ -62,7 +62,7 @@
this.f_91064_ = new DebugRenderer(this);
RealmsClient realmsclient = RealmsClient.m_239151_(this);
this.f_238717_ = new RealmsDataFetcher(realmsclient);
@@ -545,6 +_,7 @@
@@ -536,6 +_,7 @@
TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false);
}
@@ -70,34 +70,61 @@
this.f_90990_.m_85409_(this.f_91066_.m_231817_().m_231551_());
this.f_90990_.m_85424_(this.f_91066_.m_232123_().m_231551_());
this.f_90990_.m_85426_();
@@ -564,7 +_,7 @@
@@ -554,7 +_,7 @@
this.f_167847_.m_168557_(ResourceLoadStateTracker.ReloadReason.INITIAL, list);
ReloadInstance reloadinstance = this.f_91036_.m_142463_(Util.m_183991_(), this, f_90983_, list);
GameLoadTimesEvent.f_285635_.m_285833_(TelemetryProperty.f_285629_);
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, p_91084_.f_278410_);
- this.m_91150_(new LoadingOverlay(this, reloadinstance, (p_296164_) -> {
+ this.m_91150_(net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(() -> this, () -> reloadinstance, (p_296164_) -> {
Util.m_137521_(p_296164_, (p_296162_) -> {
this.m_91239_(p_296162_, minecraft$gameloadcookie);
}, () -> {
@@ -575,7 +_,7 @@
- this.m_91150_(new LoadingOverlay(this, reloadinstance, (p_210745_) -> {
+ this.m_91150_(net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(()->this, ()->reloadinstance, (p_210745_) -> {
Util.m_137521_(p_210745_, this::m_91239_, () -> {
if (SharedConstants.f_136183_) {
this.m_91273_();
@@ -562,20 +_,23 @@
this.f_167847_.m_168556_();
this.m_293750_(minecraft$gameloadcookie);
this.m_286052_();
+ if (net.minecraftforge.client.loading.ClientModLoader.completeModLoading())
+ return; // Do not overwrite the error screen if there are errors
+ // FORGE: Move opening initial screen to after startup and events are enabled
+ if (this.m_239929_()) {
+ this.m_91152_(BanNoticeScreen.m_239967_((p_278873_) -> {
+ if (p_278873_) {
+ Util.m_137581_().m_137646_("https://aka.ms/mcjavamoderation");
+ }
+
+ this.m_278684_(realmsclient, reloadinstance, p_91084_.f_278410_);
+ }, this.m_239210_()));
+ } else {
+ this.m_278684_(realmsclient, reloadinstance, p_91084_.f_278410_);
+ }
});
- }, false));
+ }, false).get());
this.f_278504_ = QuickPlayLog.m_278648_(p_91084_.f_278410_.f_278493_());
- if (this.m_239929_()) {
- this.m_91152_(BanNoticeScreen.m_239967_((p_278873_) -> {
- if (p_278873_) {
- Util.m_137581_().m_137646_("https://aka.ms/mcjavamoderation");
- }
-
- this.m_278684_(realmsclient, reloadinstance, p_91084_.f_278410_);
- }, this.m_239210_()));
- } else {
- this.m_278684_(realmsclient, reloadinstance, p_91084_.f_278410_);
- }
}
@@ -673,7 +_,7 @@
@@ -611,7 +_,7 @@
private String m_91270_() {
StringBuilder stringbuilder = new StringBuilder("Minecraft");
if (m_193589_().m_184597_()) {
- stringbuilder.append("*");
+ stringbuilder.append(' ').append(net.minecraftforge.forge.snapshots.ForgeSnapshotsMod.BRANDING_NAME).append('*');
+ stringbuilder.append("* ").append(net.minecraftforge.forge.snapshots.ForgeSnapshotsMod.BRANDING_NAME);
}
stringbuilder.append(" ");
@@ -698,6 +_,8 @@
@@ -635,6 +_,8 @@
private UserApiService m_193585_(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
try {
@@ -106,30 +133,30 @@
return p_193586_.createUserApiService(p_193587_.f_101905_.f_101942_.m_92547_());
} catch (AuthenticationException authenticationexception) {
f_90982_.error("Failed to verify authentication", (Throwable)authenticationexception);
@@ -710,7 +_,7 @@
@@ -647,7 +_,7 @@
}
private void m_91239_(Throwable p_91240_, @Nullable Minecraft.GameLoadCookie p_299515_) {
private void m_91239_(Throwable p_91240_) {
- if (this.f_91038_.m_10523_().size() > 1) {
+ if (this.f_91038_.m_10524_().stream().anyMatch(e -> !e.m_10449_())) { //Forge: This caused infinite loop if any resource packs are forced. Such as mod resources. So check if we can disable any.
this.m_91241_(p_91240_, (Component)null, p_299515_);
this.m_91241_(p_91240_, (Component)null);
} else {
Util.m_137559_(p_91240_);
@@ -802,7 +_,10 @@
@@ -739,7 +_,10 @@
}
public void m_91271_() {
- this.f_90997_.m_235232_(SearchRegistry.f_119941_, (p_231451_) -> {
- this.f_90997_.m_235232_(SearchRegistry.f_119941_, (p_231389_) -> {
+ var nameSearchKeys = net.minecraftforge.client.CreativeModeTabSearchRegistry.getNameSearchKeys();
+ var tagSearchKeys = net.minecraftforge.client.CreativeModeTabSearchRegistry.getTagSearchKeys();
+ for (var nameSearchKey : nameSearchKeys.values())
+ this.f_90997_.m_235232_(nameSearchKey, (p_231451_) -> {
+ this.f_90997_.m_235232_(nameSearchKey, (p_231389_) -> {
return new FullTextSearchTree<>((p_210797_) -> {
return p_210797_.m_41651_((Player)null, TooltipFlag.Default.f_256752_.m_257777_()).stream().map((p_231455_) -> {
return ChatFormatting.m_126649_(p_231455_.getString()).trim();
@@ -813,14 +_,18 @@
return p_210797_.m_41651_((Player)null, TooltipFlag.Default.f_256752_.m_257777_()).stream().map((p_210807_) -> {
return ChatFormatting.m_126649_(p_210807_.getString()).trim();
@@ -750,7 +_,8 @@
return Stream.of(BuiltInRegistries.f_257033_.m_7981_(p_91317_.m_41720_()));
}, p_231451_);
}, p_231389_);
});
- this.f_90997_.m_235232_(SearchRegistry.f_119942_, (p_231430_) -> {
+ for (var tagSearchKey : tagSearchKeys.values())
@@ -137,6 +164,9 @@
return new IdSearchTree<>((p_231353_) -> {
return p_231353_.m_204131_().map(TagKey::f_203868_);
}, p_231430_);
@@ -770,9 +_,12 @@
});
}, p_231451_);
});
- CreativeModeTabs.m_258007_().m_257882_((p_255439_) -> {
- this.m_231374_(SearchRegistry.f_119941_, p_255439_);
@@ -150,7 +180,7 @@
});
}
@@ -872,13 +_,13 @@
@@ -824,13 +_,13 @@
Bootstrap.m_135875_(p_91333_.m_127526_());
if (p_91333_.m_127527_() != null) {
Bootstrap.m_135875_("#@!@# Game crashed! Crash report saved to: #@!@# " + p_91333_.m_127527_());
@@ -167,7 +197,7 @@
}
}
@@ -1003,10 +_,6 @@
@@ -954,10 +_,6 @@
f_90982_.error("setScreen called from non-game thread");
}
@@ -178,27 +208,27 @@
if (p_91153_ == null && this.f_91073_ == null) {
p_91153_ = new TitleScreen();
} else if (p_91153_ == null && this.f_91074_.m_21224_()) {
@@ -1017,6 +_,19 @@
@@ -968,6 +_,19 @@
}
}
+ net.minecraftforge.client.ForgeHooksClient.clearGuiLayers(this);
+ Screen old = this.f_91080_;
+ if (p_91153_ != null) {
+ var event = net.minecraftforge.event.ForgeEventFactory.onScreenOpening(old, p_91153_);
+ if (event == null) return;
+ p_91153_ = event;
+ var event = new net.minecraftforge.client.event.ScreenEvent.Opening(old, p_91153_);
+ if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event)) return;
+ p_91153_ = event.getNewScreen();
+ }
+
+ if (old != null && p_91153_ != old) {
+ net.minecraftforge.event.ForgeEventFactory.onScreenClose(old);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Closing(old));
+ old.m_7861_();
+ }
+
this.f_91080_ = p_91153_;
if (this.f_91080_ != null) {
this.f_91080_.m_274333_();
@@ -1163,9 +_,12 @@
@@ -1113,9 +_,12 @@
RenderSystem.enableCull();
this.f_91026_.m_7238_();
if (!this.f_91079_) {
@@ -211,7 +241,7 @@
}
if (this.f_91056_ != null) {
@@ -1286,10 +_,12 @@
@@ -1240,10 +_,12 @@
this.f_90990_.m_85378_((double)i);
if (this.f_91080_ != null) {
this.f_91080_.m_6574_(this, this.f_90990_.m_85445_(), this.f_90990_.m_85446_());
@@ -224,15 +254,15 @@
this.f_91063_.m_109097_(this.f_90990_.m_85441_(), this.f_90990_.m_85442_());
this.f_91067_.m_91599_();
}
@@ -1563,6 +_,7 @@
@@ -1517,6 +_,7 @@
}
public void m_91395_() {
+ if (this.m_91396_()) net.minecraftforge.event.ForgeEventFactory.onGameShuttingDown();
+ if (this.m_91396_()) net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.GameShuttingDownEvent());
this.f_91019_ = false;
}
@@ -1592,10 +_,18 @@
@@ -1546,10 +_,18 @@
if (p_91387_ && this.f_91077_ != null && this.f_91077_.m_6662_() == HitResult.Type.BLOCK) {
BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_;
BlockPos blockpos = blockhitresult.m_82425_();
@@ -254,7 +284,7 @@
this.f_91074_.m_6674_(InteractionHand.MAIN_HAND);
}
}
@@ -1624,6 +_,8 @@
@@ -1578,6 +_,8 @@
return false;
} else {
boolean flag = false;
@@ -263,7 +293,7 @@
switch (this.f_91077_.m_6662_()) {
case ENTITY:
this.f_91072_.m_105223_(this.f_91074_, ((EntityHitResult)this.f_91077_).m_82443_());
@@ -1631,7 +_,7 @@
@@ -1585,7 +_,7 @@
case BLOCK:
BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_;
BlockPos blockpos = blockhitresult.m_82425_();
@@ -272,7 +302,7 @@
this.f_91072_.m_105269_(blockpos, blockhitresult.m_82434_());
if (this.f_91073_.m_8055_(blockpos).m_60795_()) {
flag = true;
@@ -1644,8 +_,10 @@
@@ -1598,8 +_,10 @@
}
this.f_91074_.m_36334_();
@@ -283,7 +313,7 @@
this.f_91074_.m_6674_(InteractionHand.MAIN_HAND);
return flag;
}
@@ -1661,6 +_,11 @@
@@ -1615,6 +_,11 @@
}
for(InteractionHand interactionhand : InteractionHand.values()) {
@@ -295,7 +325,7 @@
ItemStack itemstack = this.f_91074_.m_21120_(interactionhand);
if (!itemstack.m_246617_(this.f_91073_.m_246046_())) {
return;
@@ -1681,7 +_,7 @@
@@ -1635,7 +_,7 @@
}
if (interactionresult.m_19077_()) {
@@ -304,7 +334,7 @@
this.f_91074_.m_6674_(interactionhand);
}
@@ -1693,7 +_,7 @@
@@ -1647,7 +_,7 @@
int i = itemstack.m_41613_();
InteractionResult interactionresult1 = this.f_91072_.m_233732_(this.f_91074_, interactionhand, blockhitresult);
if (interactionresult1.m_19077_()) {
@@ -313,7 +343,7 @@
this.f_91074_.m_6674_(interactionhand);
if (!itemstack.m_41619_() && (itemstack.m_41613_() != i || this.f_91072_.m_105290_())) {
this.f_91063_.f_109055_.m_109320_(interactionhand);
@@ -1709,6 +_,9 @@
@@ -1663,6 +_,9 @@
}
}
@@ -323,7 +353,7 @@
if (!itemstack.m_41619_()) {
InteractionResult interactionresult2 = this.f_91072_.m_233721_(this.f_91074_, interactionhand);
if (interactionresult2.m_19077_()) {
@@ -1735,6 +_,8 @@
@@ -1689,6 +_,8 @@
--this.f_91011_;
}
@@ -332,7 +362,7 @@
this.f_91026_.m_6180_("gui");
this.f_240378_.m_240688_();
this.f_91065_.m_193832_(this.f_91012_);
@@ -1823,6 +_,7 @@
@@ -1780,6 +_,7 @@
this.f_91005_.m_120596_();
@@ -340,7 +370,7 @@
try {
this.f_91073_.m_104726_(() -> {
return true;
@@ -1838,6 +_,7 @@
@@ -1795,6 +_,7 @@
throw new ReportedException(crashreport);
}
@@ -348,7 +378,7 @@
}
this.f_91026_.m_6182_("animateTick");
@@ -1857,6 +_,8 @@
@@ -1814,6 +_,8 @@
this.f_91026_.m_6182_("keyboard");
this.f_91068_.m_90931_();
this.f_91026_.m_7238_();
@@ -357,7 +387,7 @@
}
private boolean m_91278_() {
@@ -2053,6 +_,7 @@
@@ -2011,6 +_,7 @@
}
public void m_91156_(ClientLevel p_91157_) {
@@ -365,7 +395,7 @@
ProgressScreen progressscreen = new ProgressScreen(true);
progressscreen.m_6309_(Component.m_237115_("connect.joining"));
this.m_91362_(progressscreen);
@@ -2086,10 +_,12 @@
@@ -2044,10 +_,12 @@
IntegratedServer integratedserver = this.f_91007_;
this.f_91007_ = null;
this.f_91063_.m_109150_();
@@ -378,7 +408,7 @@
if (integratedserver != null) {
this.f_91026_.m_6180_("waitForServer");
@@ -2103,6 +_,7 @@
@@ -2061,6 +_,7 @@
this.f_243981_.m_246151_();
this.f_91065_.m_93089_();
this.f_91010_ = false;
@@ -386,7 +416,7 @@
}
this.f_91073_ = null;
@@ -2227,6 +_,7 @@
@@ -2167,6 +_,7 @@
private void m_91280_() {
if (this.f_91077_ != null && this.f_91077_.m_6662_() != HitResult.Type.MISS) {
@@ -394,7 +424,7 @@
boolean flag = this.f_91074_.m_150110_().f_35937_;
BlockEntity blockentity = null;
HitResult.Type hitresult$type = this.f_91077_.m_6662_();
@@ -2239,10 +_,7 @@
@@ -2179,10 +_,7 @@
}
Block block = blockstate.m_60734_();
@@ -406,7 +436,7 @@
if (flag && Screen.m_96637_() && blockstate.m_155947_()) {
blockentity = this.f_91073_.m_7702_(blockpos);
@@ -2253,7 +_,7 @@
@@ -2193,7 +_,7 @@
}
Entity entity = ((EntityHitResult)this.f_91077_).m_82443_();
@@ -415,7 +445,7 @@
if (itemstack == null) {
return;
}
@@ -2788,6 +_,19 @@
@@ -2732,6 +_,19 @@
public void m_91312_(int p_91313_) {
this.f_91051_.m_119410_(p_91313_);
@@ -1,75 +1,85 @@
--- a/net/minecraft/client/MouseHandler.java
+++ b/net/minecraft/client/MouseHandler.java
@@ -74,6 +_,7 @@
@@ -73,6 +_,7 @@
this.f_91510_ = -1;
}
+ if (net.minecraftforge.event.ForgeEventFactory.onMouseButtonPre(p_91532_, p_91533_, p_91534_)) return;
+ if (net.minecraftforge.client.ForgeHooksClient.onMouseButtonPre(p_91532_, p_91533_, p_91534_)) return;
boolean[] aboolean = new boolean[]{false};
if (this.f_91503_.m_91265_() == null) {
if (this.f_91503_.f_91080_ == null) {
@@ -87,11 +_,19 @@
@@ -86,11 +_,19 @@
if (flag) {
screen.m_169415_();
Screen.m_96579_(() -> {
- aboolean[0] = screen.m_6375_(d0, d1, i);
+ aboolean[0] = net.minecraftforge.event.ForgeEventFactory.onScreenMouseClickedPre(screen, d0, d1, i);
+ aboolean[0] = net.minecraftforge.client.ForgeHooksClient.onScreenMouseClickedPre(screen, d0, d1, i);
+ if (!aboolean[0]) {
+ aboolean[0] = this.f_91503_.f_91080_.m_6375_(d0, d1, i);
+ aboolean[0] = net.minecraftforge.event.ForgeEventFactory.onScreenMouseClickedPost(screen, d0, d1, i, aboolean[0]);
+ aboolean[0] = net.minecraftforge.client.ForgeHooksClient.onScreenMouseClickedPost(screen, d0, d1, i, aboolean[0]);
+ }
}, "mouseClicked event handler", screen.getClass().getCanonicalName());
} else {
Screen.m_96579_(() -> {
- aboolean[0] = screen.m_6348_(d0, d1, i);
+ aboolean[0] = net.minecraftforge.event.ForgeEventFactory.onScreenMouseReleasedPre(screen, d0, d1, i);
+ aboolean[0] = net.minecraftforge.client.ForgeHooksClient.onScreenMouseReleasedPre(screen, d0, d1, i);
+ if (!aboolean[0]) {
+ aboolean[0] = this.f_91503_.f_91080_.m_6348_(d0, d1, i);
+ aboolean[0] = net.minecraftforge.event.ForgeEventFactory.onScreenMouseReleasedPost(screen, d0, d1, i, aboolean[0]);
+ aboolean[0] = net.minecraftforge.client.ForgeHooksClient.onScreenMouseReleasedPost(screen, d0, d1, i, aboolean[0]);
+ }
}, "mouseReleased event handler", screen.getClass().getCanonicalName());
}
}
@@ -116,6 +_,7 @@
@@ -114,19 +_,26 @@
}
}
}
+ net.minecraftforge.event.ForgeEventFactory.onMouseButtonPost(p_91532_, p_91533_, p_91534_);
-
+ net.minecraftforge.client.ForgeHooksClient.onMouseButtonPost(p_91532_, p_91533_, p_91534_);
}
}
@@ -129,8 +_,10 @@
private void m_91526_(long p_91527_, double p_91528_, double p_91529_) {
if (p_91527_ == Minecraft.m_91087_().m_91268_().m_85439_()) {
- double d0 = (this.f_91503_.f_91066_.m_231821_().m_231551_() ? Math.signum(p_91529_) : p_91529_) * this.f_91503_.f_91066_.m_232122_().m_231551_();
+ // FORGE: Allows for Horizontal Scroll to be recognized as Vertical Scroll - Fixes MC-121772
+ double offset = p_91529_;
+ if (Minecraft.f_91002_ && p_91529_ == 0) {
+ offset = p_91528_;
+ }
+ double d0 = (this.f_91503_.f_91066_.m_231821_().m_231551_() ? Math.signum(offset) : offset) * this.f_91503_.f_91066_.m_232122_().m_231551_();
if (this.f_91503_.m_91265_() == null) {
if (this.f_91503_.f_91080_ != null) {
double d3 = this.f_91507_ * (double)this.f_91503_.m_91268_().m_85445_() / (double)this.f_91503_.m_91268_().m_85443_();
double d4 = this.f_91508_ * (double)this.f_91503_.m_91268_().m_85446_() / (double)this.f_91503_.m_91268_().m_85444_();
- this.f_91503_.f_91080_.m_6050_(d3, d4, d1, d2);
double d1 = this.f_91507_ * (double)this.f_91503_.m_91268_().m_85445_() / (double)this.f_91503_.m_91268_().m_85443_();
double d2 = this.f_91508_ * (double)this.f_91503_.m_91268_().m_85446_() / (double)this.f_91503_.m_91268_().m_85444_();
- this.f_91503_.f_91080_.m_6050_(d1, d2, d0);
this.f_91503_.f_91080_.m_169415_();
+ if (net.minecraftforge.event.ForgeEventFactory.onScreenMouseScrollPre(this.f_91503_.f_91080_, d3, d4, d1, d2)) return;
+ if (this.f_91503_.f_91080_.m_6050_(d3, d4, d1, d2)) return;
+ net.minecraftforge.event.ForgeEventFactory.onScreenMouseScrollPost(this.f_91503_.f_91080_, d3, d4, d1, d2);
+ if (net.minecraftforge.client.ForgeHooksClient.onScreenMouseScrollPre(this, this.f_91503_.f_91080_, d0)) return;
+ if (this.f_91503_.f_91080_.m_6050_(d1, d2, d0)) return;
+ net.minecraftforge.client.ForgeHooksClient.onScreenMouseScrollPost(this, this.f_91503_.f_91080_, d0);
} else if (this.f_91503_.f_91074_ != null) {
if (this.f_291070_ != 0.0D && Math.signum(d1) != Math.signum(this.f_291070_)) {
this.f_291070_ = 0.0D;
@@ -151,6 +_,7 @@
this.f_291070_ -= (double)j;
this.f_291867_ -= (double)i;
int k = i == 0 ? -j : i;
+ if (net.minecraftforge.event.ForgeEventFactory.onMouseScroll(this, d1, d2)) return;
if (this.f_91518_ != 0.0D && Math.signum(d0) != Math.signum(this.f_91518_)) {
this.f_91518_ = 0.0D;
@@ -139,6 +_,7 @@
}
this.f_91518_ -= (double)i;
+ if (net.minecraftforge.client.ForgeHooksClient.onMouseScroll(this, d0)) return;
if (this.f_91503_.f_91074_.m_5833_()) {
if (this.f_91503_.f_91065_.m_93085_().m_94768_()) {
this.f_91503_.f_91065_.m_93085_().m_205380_(-k);
@@ -219,7 +_,9 @@
this.f_91503_.f_91065_.m_93085_().m_205380_(-i);
@@ -207,7 +_,9 @@
double d2 = (p_91563_ - this.f_91507_) * (double)this.f_91503_.m_91268_().m_85445_() / (double)this.f_91503_.m_91268_().m_85443_();
double d3 = (p_91564_ - this.f_91508_) * (double)this.f_91503_.m_91268_().m_85446_() / (double)this.f_91503_.m_91268_().m_85444_();
Screen.m_96579_(() -> {
- screen.m_7979_(d0, d1, this.f_91510_, d2, d3);
+ if (net.minecraftforge.event.ForgeEventFactory.onScreenMouseDragPre(screen, d0, d1, this.f_91510_, d2, d3)) return;
+ if (net.minecraftforge.client.ForgeHooksClient.onScreenMouseDragPre(screen, d0, d1, this.f_91510_, d2, d3)) return;
+ if (screen.m_7979_(d0, d1, this.f_91510_, d2, d3)) return;
+ net.minecraftforge.event.ForgeEventFactory.onScreenMouseDragPost(screen, d0, d1, this.f_91510_, d2, d3);
+ net.minecraftforge.client.ForgeHooksClient.onScreenMouseDragPost(screen, d0, d1, this.f_91510_, d2, d3);
}, "mouseDragged event handler", screen.getClass().getCanonicalName());
}
@@ -302,6 +_,14 @@
@@ -290,6 +_,14 @@
public double m_91594_() {
return this.f_91508_;
@@ -1,16 +1,16 @@
--- a/net/minecraft/client/Options.java
+++ b/net/minecraft/client/Options.java
@@ -507,7 +_,8 @@
@@ -545,7 +_,8 @@
}, new OptionInstance.LazyEnum<>(() -> {
return Stream.concat(Stream.of(""), Minecraft.m_91087_().m_91106_().m_194525_().stream()).toList();
}, (p_232011_) -> {
- return Minecraft.m_91087_().m_91396_() && p_232011_ != "" && !Minecraft.m_91087_().m_91106_().m_194525_().contains(p_232011_) ? Optional.empty() : Optional.of(p_232011_);
+ // FORGE: fix incorrect string comparison - PR #8767
+ return Minecraft.m_91087_().m_91396_() && (p_232011_ == null || !p_232011_.isEmpty()) && !Minecraft.m_91087_().m_91106_().m_194525_().contains(p_232011_) ? Optional.empty() : Optional.of(p_232011_);
}, Codec.STRING), "", (p_299350_) -> {
}, Codec.STRING), "", (p_275584_) -> {
SoundManager soundmanager = Minecraft.m_91087_().m_91106_();
soundmanager.m_194526_();
@@ -835,6 +_,7 @@
@@ -869,6 +_,7 @@
}
public Options(Minecraft p_92138_, File p_92139_) {
@@ -18,7 +18,7 @@
this.f_92060_ = p_92138_;
this.f_92110_ = new File(p_92139_, "options.txt");
boolean flag = p_92138_.m_91103_();
@@ -957,11 +_,21 @@
@@ -990,11 +_,21 @@
p_168428_.m_213982_("telemetryOptInExtra", this.f_260461_);
this.f_263744_ = p_168428_.m_142682_("onboardAccessibility", this.f_263744_);
@@ -42,7 +42,7 @@
}
}
@@ -980,6 +_,9 @@
@@ -1013,6 +_,9 @@
}
public void m_92140_() {
@@ -52,7 +52,7 @@
try {
if (!this.f_92110_.exists()) {
return;
@@ -1008,7 +_,8 @@
@@ -1041,7 +_,8 @@
}
}
@@ -62,15 +62,15 @@
@Nullable
private String m_168458_(String p_168459_) {
return compoundtag1.m_128441_(p_168459_) ? compoundtag1.m_128461_(p_168459_) : null;
@@ -1181,6 +_,7 @@
@@ -1204,6 +_,7 @@
}
public void m_92172_() {
+ if (net.minecraftforge.client.loading.ClientModLoader.isLoading()) return; //Don't save settings before mods add keybindigns and the like to prevent them from being deleted.
if (this.f_92060_.f_91074_ != null) {
this.f_92060_.f_91074_.f_108617_.m_295327_(new ServerboundClientInformationPacket(this.m_294596_()));
}
@@ -1239,6 +_,23 @@
int i = 0;
@@ -1268,6 +_,23 @@
}
p_92146_.m_10509_(set);
@@ -0,0 +1,49 @@
--- a/net/minecraft/client/User.java
+++ b/net/minecraft/client/User.java
@@ -21,8 +_,22 @@
private final Optional<String> f_193796_;
private final Optional<String> f_193797_;
private final User.Type f_92538_;
+ /** Forge: Cache of the local session's GameProfile properties. */
+ private com.mojang.authlib.properties.PropertyMap properties;
public User(String p_193799_, String p_193800_, String p_193801_, Optional<String> p_193802_, Optional<String> p_193803_, User.Type p_193804_) {
+ if (p_193799_ == null || p_193799_.isEmpty()) {
+ p_193799_ = "MissingName";
+ p_193800_ = p_193801_ = "NotValid";
+ org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger(getClass().getName());
+ logger.warn("=========================================================");
+ logger.warn("WARNING!! the username was not set for this session, typically");
+ logger.warn("this means you installed Forge incorrectly. We have set your");
+ logger.warn("name to \"MissingName\" and your session to nothing. Please");
+ logger.warn("check your installation and post a console log from the launcher");
+ logger.warn("when asking for help!");
+ logger.warn("=========================================================");
+ }
this.f_92535_ = p_193799_;
this.f_92536_ = p_193800_;
this.f_92537_ = p_193801_;
@@ -64,8 +_,22 @@
}
}
+ //For internal use only. Modders should never need to use this.
+ public void setProperties(com.mojang.authlib.properties.PropertyMap properties) {
+ if (this.properties == null)
+ this.properties = properties;
+ }
+
+ public boolean hasCachedProperties() {
+ return properties != null;
+ }
+
public GameProfile m_92548_() {
- return new GameProfile(this.m_240411_(), this.m_92546_());
+ // FORGE: Add cached GameProfile properties to returned GameProfile. This helps to cut down on calls to the session service.
+ GameProfile ret = new GameProfile(this.m_240411_(), this.m_92546_());
+ if (this.properties != null)
+ ret.getProperties().putAll(this.properties);
+ return ret;
}
public User.Type m_168638_() {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/Gui.java
+++ b/net/minecraft/client/gui/Gui.java
@@ -453,6 +_,8 @@
@@ -424,6 +_,8 @@
for(MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
MobEffect mobeffect = mobeffectinstance.m_19544_();
@@ -9,7 +9,7 @@
if (mobeffectinstance.m_19575_()) {
int i = this.f_92977_;
int j = 1;
@@ -481,6 +_,7 @@
@@ -452,6 +_,7 @@
}
}
@@ -17,7 +17,7 @@
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.m_118732_(mobeffect);
int i1 = j;
float f1 = f;
@@ -601,16 +_,21 @@
@@ -572,16 +_,21 @@
}
public void m_280295_(GuiGraphics p_283501_) {
@@ -42,7 +42,7 @@
if (!this.f_92986_.f_91072_.m_105205_()) {
k += 14;
}
@@ -622,7 +_,13 @@
@@ -593,7 +_,13 @@
if (l > 0) {
p_283501_.m_280509_(j - 2, k - 2, j + i + 2, k + 9 + 2, this.f_92986_.f_91066_.m_92143_(0));
@@ -57,7 +57,7 @@
}
}
@@ -1069,7 +_,7 @@
@@ -1037,7 +_,7 @@
ItemStack itemstack = this.f_92986_.f_91074_.m_150109_().m_36056_();
if (itemstack.m_41619_()) {
this.f_92993_ = 0;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/GuiGraphics.java
+++ b/net/minecraft/client/gui/GuiGraphics.java
@@ -55,7 +_,7 @@
@@ -56,7 +_,7 @@
import org.joml.Vector2ic;
@OnlyIn(Dist.CLIENT)
@@ -9,7 +9,7 @@
public static final float f_289044_ = 10000.0F;
public static final float f_289038_ = -10000.0F;
private static final int f_279564_ = 2;
@@ -271,6 +_,11 @@
@@ -270,6 +_,11 @@
}
public int m_280056_(Font p_283343_, @Nullable String p_281896_, int p_283569_, int p_283418_, int p_281560_, boolean p_282130_) {
@@ -21,7 +21,7 @@
if (p_281896_ == null) {
return 0;
} else {
@@ -285,6 +_,11 @@
@@ -284,6 +_,11 @@
}
public int m_280649_(Font p_282636_, FormattedCharSequence p_281596_, int p_281586_, int p_282816_, int p_281743_, boolean p_282394_) {
@@ -33,7 +33,27 @@
int i = p_282636_.m_272191_(p_281596_, (float)p_281586_, (float)p_282816_, p_281743_, p_282394_, this.f_279612_.m_85850_().m_252922_(), this.f_279627_, Font.DisplayMode.NORMAL, 0, 15728880);
this.m_286081_();
return i;
@@ -511,6 +_,7 @@
@@ -405,6 +_,10 @@
}
public void m_280543_(ResourceLocation p_283059_, int p_283575_, int p_283192_, int p_281790_, int p_283642_, int p_282691_, int p_281912_, int p_281728_, int p_282324_) {
+ blitRepeating(p_283059_, p_283575_, p_283192_, p_281790_, p_283642_, p_282691_, p_281912_, p_281728_, p_282324_, 256, 256);
+ }
+
+ public void blitRepeating(ResourceLocation p_283059_, int p_283575_, int p_283192_, int p_281790_, int p_283642_, int p_282691_, int p_281912_, int p_281728_, int p_282324_, int textureWidth, int textureHeight) {
int i = p_283575_;
int j;
@@ -417,7 +_,7 @@
for(IntIterator intiterator1 = m_280358_(p_283642_, p_282324_); intiterator1.hasNext(); l += i1) {
i1 = intiterator1.nextInt();
int j1 = (p_282324_ - i1) / 2;
- this.m_280218_(p_283059_, i, l, p_282691_ + k, p_281912_ + j1, j, i1);
+ this.m_280163_(p_283059_, i, l, p_282691_ + k, p_281912_ + j1, j, i1, textureWidth, textureHeight);
}
}
@@ -477,6 +_,7 @@
crashreportcategory.m_128165_("Item Type", () -> {
return String.valueOf((Object)p_281675_.m_41720_());
});
@@ -41,7 +61,7 @@
crashreportcategory.m_128165_("Item Damage", () -> {
return String.valueOf(p_281675_.m_41773_());
});
@@ -558,18 +_,26 @@
@@ -524,18 +_,26 @@
}
this.f_279612_.m_85849_();
@@ -72,7 +92,7 @@
this.m_280497_(p_283128_, list, p_283678_, p_281696_, DefaultTooltipPositioner.f_262752_);
}
@@ -578,7 +_,15 @@
@@ -544,7 +_,22 @@
}
public void m_280666_(Font p_282739_, List<Component> p_281832_, int p_282191_, int p_282446_) {
@@ -85,11 +105,18 @@
+ this.tooltipStack = stack;
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(stack, tooltips, mouseX, m_280182_(), m_280206_(), font);
+ this.m_280497_(font, components, mouseX, mouseY, DefaultTooltipPositioner.f_262752_);
+ this.tooltipStack = ItemStack.f_41583_;
+ }
+
+ public void renderComponentTooltipFromElements(Font font, List<com.mojang.datafixers.util.Either<FormattedText, TooltipComponent>> elements, int mouseX, int mouseY, ItemStack stack) {
+ this.tooltipStack = stack;
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponentsFromElements(stack, elements, mouseX, m_280182_(), m_280206_(), font);
+ this.m_280497_(font, components, mouseX, mouseY, DefaultTooltipPositioner.f_262752_);
+ this.tooltipStack = ItemStack.f_41583_;
}
public void m_280245_(Font p_282192_, List<? extends FormattedCharSequence> p_282297_, int p_281680_, int p_283325_) {
@@ -591,11 +_,13 @@
@@ -557,11 +_,13 @@
private void m_280497_(Font p_282675_, List<ClientTooltipComponent> p_282615_, int p_283230_, int p_283417_, ClientTooltipPositioner p_282442_) {
if (!p_282615_.isEmpty()) {
@@ -104,7 +131,7 @@
if (k > i) {
i = k;
}
@@ -605,20 +_,21 @@
@@ -571,20 +_,21 @@
int i2 = i;
int j2 = j;
@@ -129,7 +156,7 @@
k1 += clienttooltipcomponent1.m_142103_() + (l1 == 0 ? 2 : 0);
}
@@ -626,7 +_,7 @@
@@ -592,7 +_,7 @@
for(int k2 = 0; k2 < p_282615_.size(); ++k2) {
ClientTooltipComponent clienttooltipcomponent2 = p_282615_.get(k2);
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/gui/MapRenderer.java
+++ b/net/minecraft/client/gui/MapRenderer.java
@@ -118,6 +_,7 @@
for(MapDecoration mapdecoration : this.f_93280_.m_164811_()) {
if (!p_93294_ || mapdecoration.m_77809_()) {
+ if (mapdecoration.render(k)) { k++; continue; }
p_93292_.m_85836_();
p_93292_.m_252880_(0.0F + (float)mapdecoration.m_77804_() / 2.0F + 64.0F, 0.0F + (float)mapdecoration.m_77805_() / 2.0F + 64.0F, -0.02F);
p_93292_.m_252781_(Axis.f_252403_.m_252977_((float)(mapdecoration.m_77806_() * 360) / 16.0F));
@@ -1,11 +1,11 @@
--- a/net/minecraft/client/gui/components/AbstractButton.java
+++ b/net/minecraft/client/gui/components/AbstractButton.java
@@ -29,7 +_,7 @@
@@ -32,7 +_,7 @@
RenderSystem.enableDepthTest();
p_281670_.m_292816_(f_290895_.m_295557_(this.f_93623_, this.m_198029_()), this.m_252754_(), this.m_252907_(), this.m_5711_(), this.m_93694_());
p_281670_.m_280027_(f_93617_, this.m_252754_(), this.m_252907_(), this.m_5711_(), this.m_93694_(), 20, 4, 200, 20, 0, this.m_274533_());
p_281670_.m_280246_(1.0F, 1.0F, 1.0F, 1.0F);
- int i = this.f_93623_ ? 16777215 : 10526880;
+ int i = getFGColor();
this.m_280465_(p_281670_, minecraft.f_91062_, i | Mth.m_14167_(this.f_93625_ * 255.0F) << 24);
this.m_280139_(p_281670_, minecraft.f_91062_, i | Mth.m_14167_(this.f_93625_ * 255.0F) << 24);
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/AbstractSelectionList.java
+++ b/net/minecraft/client/gui/components/AbstractSelectionList.java
@@ -504,6 +_,13 @@
@@ -514,6 +_,13 @@
return new ScreenRectangle(this.f_93393_, this.f_93390_, this.f_93392_ - this.f_93393_, this.f_93391_ - this.f_93390_);
}
@@ -1,9 +1,22 @@
--- a/net/minecraft/client/gui/components/AbstractWidget.java
+++ b/net/minecraft/client/gui/components/AbstractWidget.java
@@ -259,6 +_,19 @@
this.f_93616_ = p_93693_;
@@ -234,6 +_,10 @@
this.f_93618_ = p_93675_;
}
+ public void setHeight(int value) {
+ this.f_93619_ = value;
+ }
+
public void m_93650_(float p_93651_) {
this.f_93625_ = p_93651_;
}
@@ -264,6 +_,19 @@
public void m_93692_(boolean p_93693_) {
this.f_93616_ = p_93693_;
+ }
+
+ public static final int UNSET_FG_COLOR = -1;
+ protected int packedFGColor = UNSET_FG_COLOR;
+ public int getFGColor() {
@@ -15,8 +28,6 @@
+ }
+ public void clearFGColor() {
+ this.packedFGColor = UNSET_FG_COLOR;
+ }
+
}
public NarratableEntry.NarrationPriority m_142684_() {
if (this.m_93696_()) {
return NarratableEntry.NarrationPriority.FOCUSED;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/BossHealthOverlay.java
+++ b/net/minecraft/client/gui/components/BossHealthOverlay.java
@@ -36,13 +_,16 @@
@@ -33,13 +_,16 @@
for(LerpingBossEvent lerpingbossevent : this.f_93699_.values()) {
int k = i / 2 - 91;
@@ -1,19 +1,6 @@
--- a/net/minecraft/client/gui/components/DebugScreenOverlay.java
+++ b/net/minecraft/client/gui/components/DebugScreenOverlay.java
@@ -93,9 +_,9 @@
@Nullable
private CompletableFuture<LevelChunk> f_94036_;
private boolean f_291101_;
- private boolean f_291871_;
- private boolean f_290551_;
- private boolean f_291005_;
+ protected boolean f_291871_;
+ protected boolean f_290551_;
+ protected boolean f_291005_;
private final SampleLogger f_291039_ = new SampleLogger();
private final SampleLogger f_291524_ = new SampleLogger();
private final SampleLogger f_290653_ = new SampleLogger();
@@ -430,6 +_,7 @@
@@ -403,6 +_,7 @@
list.add("");
list.add(ChatFormatting.UNDERLINE + "Targeted Entity");
list.add(String.valueOf((Object)BuiltInRegistries.f_256780_.m_7981_(entity.m_6095_())));
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/ChatScreen.java
+++ b/net/minecraft/client/gui/screens/ChatScreen.java
@@ -224,7 +_,7 @@
@@ -225,7 +_,7 @@
this.f_96541_.f_91074_.f_108617_.m_246175_(p_242400_);
}
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/gui/screens/ConnectScreen.java
+++ b/net/minecraft/client/gui/screens/ConnectScreen.java
@@ -84,6 +_,8 @@
@@ -86,6 +_,8 @@
}
if (optional.isEmpty()) {
if (!optional.isPresent()) {
+ ConnectScreen.f_95683_.error("Couldn't connect to server: Unknown host \"{}\"", p_249536_.m_171863_());
+ net.minecraftforge.network.DualStackUtils.logInitialPreferences();
p_251955_.execute(() -> {
@@ -1,7 +1,7 @@
--- a/net/minecraft/client/gui/screens/OptionsScreen.java
+++ b/net/minecraft/client/gui/screens/OptionsScreen.java
@@ -150,6 +_,14 @@
p_283520_.m_280653_(this.f_96547_, this.f_96539_, this.f_96543_ / 2, 15, 16777215);
@@ -151,6 +_,14 @@
super.m_88315_(p_283520_, p_281826_, p_283378_, p_281975_);
}
+ @Override
@@ -1,10 +1,10 @@
--- a/net/minecraft/client/gui/screens/PauseScreen.java
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
@@ -88,6 +_,7 @@
@@ -82,6 +_,7 @@
} else {
gridlayout$rowhelper.m_264139_(this.m_262456_(f_262254_, SocialInteractionsScreen::new));
}
+ gridlayout$rowhelper.m_264108_(Button.m_253074_(Component.m_237115_("fml.menu.mods"), button -> this.f_96541_.m_91152_(new net.minecraftforge.client.gui.ModListScreen(this))).m_252780_(f_262268_).m_253136_(), 2);
Component component = this.f_96541_.m_91090_() ? f_262217_ : CommonComponents.f_290546_;
Component component = this.f_96541_.m_91090_() ? f_262217_ : f_262246_;
this.f_252482_ = gridlayout$rowhelper.m_264108_(Button.m_253074_(component, (p_280815_) -> {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/Screen.java
+++ b/net/minecraft/client/gui/screens/Screen.java
@@ -207,7 +_,7 @@
@@ -205,7 +_,7 @@
}
public void m_7379_() {
@@ -9,7 +9,7 @@
}
protected <T extends GuiEventListener & Renderable & NarratableEntry> T m_142416_(T p_169406_) {
@@ -319,7 +_,10 @@
@@ -317,7 +_,10 @@
this.f_96543_ = p_96608_;
this.f_96544_ = p_96609_;
if (!this.f_267454_) {
@@ -20,7 +20,7 @@
} else {
this.m_267719_();
}
@@ -332,7 +_,10 @@
@@ -330,7 +_,10 @@
protected void m_232761_() {
this.m_169413_();
this.m_264131_();
@@ -31,15 +31,15 @@
}
public List<? extends GuiEventListener> m_6702_() {
@@ -354,6 +_,7 @@
public void m_280273_(GuiGraphics p_283688_, int p_299421_, int p_298679_, float p_297268_) {
@@ -352,6 +_,7 @@
public void m_280273_(GuiGraphics p_283688_) {
if (this.f_96541_.f_91073_ != null) {
this.m_293900_(p_283688_);
p_283688_.m_280024_(0, 0, this.f_96543_, this.f_96544_, -1072689136, -804253680);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.BackgroundRendered(this, p_283688_));
} else {
this.m_280039_(p_283688_);
}
@@ -369,6 +_,7 @@
@@ -363,6 +_,7 @@
int i = 32;
p_282281_.m_280398_(f_279548_, 0, 0, 0, 0.0F, 0.0F, this.f_96543_, this.f_96544_, 32, 32);
p_282281_.m_280246_(1.0F, 1.0F, 1.0F, 1.0F);
@@ -47,7 +47,7 @@
}
public boolean m_7043_() {
@@ -462,6 +_,10 @@
@@ -456,6 +_,10 @@
public void m_7400_(List<Path> p_96591_) {
}
@@ -58,7 +58,7 @@
private void m_169380_(long p_169381_, boolean p_169382_) {
this.f_169377_ = Util.m_137550_() + p_169381_;
if (p_169382_) {
@@ -628,5 +_,13 @@
@@ -622,5 +_,13 @@
this.f_169421_ = p_169425_;
this.f_169422_ = p_169426_;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/TitleScreen.java
+++ b/net/minecraft/client/gui/screens/TitleScreen.java
@@ -64,6 +_,7 @@
@@ -63,6 +_,7 @@
@Nullable
private TitleScreen.WarningLabel f_232768_;
private final LogoRenderer f_263781_;
@@ -8,7 +8,7 @@
public TitleScreen() {
this(false);
@@ -114,11 +_,15 @@
@@ -113,11 +_,15 @@
int j = this.f_96543_ - i - 2;
int k = 24;
int l = this.f_96544_ / 4 + 48;
@@ -22,9 +22,9 @@
}
+ modUpdateNotification = net.minecraftforge.client.gui.TitleScreenModUpdateIndicator.init(this, modButton);
SpriteIconButton spriteiconbutton = this.m_142416_(CommonButtons.m_292713_(20, (p_280830_) -> {
this.m_142416_(new ImageButton(this.f_96543_ / 2 - 124, l + 72 + 12, 20, 20, 0, 106, 20, Button.f_93617_, 256, 256, (p_280830_) -> {
this.f_96541_.m_91152_(new LanguageSelectScreen(this, this.f_96541_.f_91066_, this.f_96541_.m_91102_()));
@@ -164,7 +_,7 @@
@@ -162,7 +_,7 @@
}).m_252987_(this.f_96543_ / 2 - 100, p_96764_ + p_96765_ * 1, 200, 20).m_257505_(tooltip).m_253136_())).f_93623_ = flag;
(this.m_142416_(Button.m_253074_(Component.m_237115_("menu.online"), (p_210872_) -> {
this.m_96793_();
@@ -33,7 +33,7 @@
}
@Nullable
@@ -248,6 +_,7 @@
@@ -244,6 +_,7 @@
this.f_232768_.m_280409_(p_282860_, i);
}
@@ -41,7 +41,7 @@
if (this.f_96721_ != null) {
this.f_96721_.m_280672_(p_282860_, this.f_96543_, this.f_96547_, i);
}
@@ -263,7 +_,14 @@
@@ -259,7 +_,14 @@
s = s + I18n.m_118938_("menu.modded");
}
@@ -57,7 +57,7 @@
for(GuiEventListener guieventlistener : this.m_6702_()) {
if (guieventlistener instanceof AbstractWidget) {
@@ -276,6 +_,7 @@
@@ -272,6 +_,7 @@
RenderSystem.enableDepthTest();
this.f_96726_.m_88315_(p_282860_, p_281753_, p_283539_, p_282628_);
}
@@ -1,18 +1,18 @@
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
@@ -38,6 +_,7 @@
@@ -36,6 +_,7 @@
private int f_97141_ = Integer.MIN_VALUE;
private float f_97142_;
private boolean f_97143_;
+ private int page;
public AdvancementTab(Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, AdvancementNode p_297568_, DisplayInfo p_97150_) {
public AdvancementTab(Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, Advancement p_97149_, DisplayInfo p_97150_) {
this.f_97126_ = p_97145_;
@@ -52,6 +_,15 @@
this.m_97175_(this.f_97134_, p_297568_.m_295246_());
@@ -50,6 +_,15 @@
this.m_97175_(this.f_97134_, p_97149_);
}
+ public AdvancementTab(Minecraft mc, AdvancementsScreen screen, AdvancementTabType type, int index, int page, AdvancementNode adv, DisplayInfo info) {
+ public AdvancementTab(Minecraft mc, AdvancementsScreen screen, AdvancementTabType type, int index, int page, Advancement adv, DisplayInfo info) {
+ this(mc, screen, type, index, adv, info);
+ this.page = page;
+ }
@@ -24,14 +24,14 @@
public AdvancementTabType m_169538_() {
return this.f_97128_;
}
@@ -146,8 +_,8 @@
@@ -143,8 +_,8 @@
return null;
} else {
for(AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
- if (p_97173_ < advancementtabtype.m_97210_()) {
- return new AdvancementTab(p_97171_, p_97172_, advancementtabtype, p_97173_, p_299876_, optional.get());
- return new AdvancementTab(p_97171_, p_97172_, advancementtabtype, p_97173_, p_97174_, p_97174_.m_138320_());
+ if ((p_97173_ % AdvancementTabType.MAX_TABS) < advancementtabtype.m_97210_()) {
+ return new AdvancementTab(p_97171_, p_97172_, advancementtabtype, p_97173_ % AdvancementTabType.MAX_TABS, p_97173_ / AdvancementTabType.MAX_TABS, p_299876_, optional.get());
+ return new AdvancementTab(p_97171_, p_97172_, advancementtabtype, p_97173_ % AdvancementTabType.MAX_TABS, p_97173_ / AdvancementTabType.MAX_TABS, p_97174_, p_97174_.m_138320_());
}
p_97173_ -= advancementtabtype.m_97210_();
@@ -1,10 +1,10 @@
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTabType.java
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTabType.java
@@ -13,6 +_,7 @@
LEFT(new AdvancementTabType.Sprites(new ResourceLocation("advancements/tab_left_top_selected"), new ResourceLocation("advancements/tab_left_middle_selected"), new ResourceLocation("advancements/tab_left_bottom_selected")), new AdvancementTabType.Sprites(new ResourceLocation("advancements/tab_left_top"), new ResourceLocation("advancements/tab_left_middle"), new ResourceLocation("advancements/tab_left_bottom")), 32, 28, 5),
RIGHT(new AdvancementTabType.Sprites(new ResourceLocation("advancements/tab_right_top_selected"), new ResourceLocation("advancements/tab_right_middle_selected"), new ResourceLocation("advancements/tab_right_bottom_selected")), new AdvancementTabType.Sprites(new ResourceLocation("advancements/tab_right_top"), new ResourceLocation("advancements/tab_right_middle"), new ResourceLocation("advancements/tab_right_bottom")), 32, 28, 5);
@@ -12,6 +_,7 @@
LEFT(0, 64, 32, 28, 5),
RIGHT(96, 64, 32, 28, 5);
+ public static final int MAX_TABS = java.util.Arrays.stream(values()).mapToInt(e -> e.f_97199_).sum();
private final AdvancementTabType.Sprites f_291110_;
private final AdvancementTabType.Sprites f_291777_;
private final int f_97195_;
private final int f_97196_;
private final int f_97197_;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
@@ -42,6 +_,7 @@
@@ -41,6 +_,7 @@
@Nullable
private AdvancementTab f_97336_;
private boolean f_97337_;
@@ -8,9 +8,9 @@
public AdvancementsScreen(ClientAdvancements p_97340_) {
super(GameNarrator.f_93310_);
@@ -58,7 +_,15 @@
@@ -56,7 +_,15 @@
} else {
this.f_97334_.m_104401_(this.f_97336_ == null ? null : this.f_97336_.m_293004_().m_295246_(), true);
this.f_97334_.m_104401_(this.f_97336_ == null ? null : this.f_97336_.m_97182_(), true);
}
-
+ if (this.f_97335_.size() > AdvancementTabType.MAX_TABS) {
@@ -25,19 +25,19 @@
}
public void m_7861_() {
@@ -76,7 +_,7 @@
@@ -74,7 +_,7 @@
int j = (this.f_96544_ - 140) / 2;
for(AdvancementTab advancementtab : this.f_97335_.values()) {
- if (advancementtab.m_97154_(i, j, p_97343_, p_97344_)) {
+ if (advancementtab.getPage() == tabPage && advancementtab.m_97154_(i, j, p_97343_, p_97344_)) {
this.f_97334_.m_104401_(advancementtab.m_293004_().m_295246_(), true);
this.f_97334_.m_104401_(advancementtab.m_97182_(), true);
break;
}
@@ -100,9 +_,15 @@
@@ -98,9 +_,15 @@
int i = (this.f_96543_ - 252) / 2;
int j = (this.f_96544_ - 140) / 2;
this.m_280273_(p_282589_, p_282255_, p_283354_, p_283123_);
this.m_280273_(p_282589_);
+ if (maxPages != 0) {
+ net.minecraft.network.chat.Component page = Component.m_237113_(String.format("%d / %d", tabPage + 1, maxPages + 1));
+ int width = this.f_96547_.m_92852_(page);
@@ -50,7 +50,7 @@
}
public boolean m_7979_(double p_97347_, double p_97348_, int p_97349_, double p_97350_, double p_97351_) {
@@ -146,10 +_,12 @@
@@ -135,10 +_,12 @@
p_283395_.m_280218_(f_97329_, p_281890_, p_282532_, 0, 0, 252, 140);
if (this.f_97335_.size() > 1) {
for(AdvancementTab advancementtab : this.f_97335_.values()) {
@@ -63,7 +63,7 @@
advancementtab1.m_280485_(p_283395_, p_281890_, p_282532_);
}
}
@@ -169,7 +_,7 @@
@@ -158,7 +_,7 @@
if (this.f_97335_.size() > 1) {
for(AdvancementTab advancementtab : this.f_97335_.values()) {
@@ -9,9 +9,11 @@
}
public int m_5759_() {
@@ -129,10 +_,11 @@
@@ -128,11 +_,13 @@
this.f_193911_ = p_193917_;
this.f_193912_ = Button.m_253074_(p_193917_, (p_269618_) -> {
KeyBindsList.this.f_193858_.f_193975_ = p_193916_;
+ p_193916_.setKeyModifierAndCode(null, com.mojang.blaze3d.platform.InputConstants.f_84822_);
KeyBindsList.this.m_269130_();
- }).m_252987_(0, 0, 75, 20).m_252778_((p_253311_) -> {
+ }).m_252987_(0, 0, 75 + 20 /* Forge: Add space */, 20).m_252778_((p_253311_) -> {
@@ -13,14 +13,34 @@
public boolean m_7933_(int p_193987_, int p_193988_, int p_193989_) {
if (this.f_193975_ != null) {
if (p_193987_ == 256) {
+ this.f_193975_.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.getActiveModifier(), InputConstants.f_84822_);
+ this.f_193975_.setKeyModifierAndCode(null, InputConstants.f_84822_);
this.f_96282_.m_92159_(this.f_193975_, InputConstants.f_84822_);
} else {
+ this.f_193975_.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.getActiveModifier(), InputConstants.m_84827_(p_193987_, p_193988_));
+ this.f_193975_.setKeyModifierAndCode(null, InputConstants.m_84827_(p_193987_, p_193988_));
this.f_96282_.m_92159_(this.f_193975_, InputConstants.m_84827_(p_193987_, p_193988_));
}
+ if(!net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(this.f_193975_.getKey()))
+ if (p_193987_ == 256 || !net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(this.f_193975_.getKey()))
this.f_193975_ = null;
this.f_193976_ = Util.m_137550_();
this.f_193977_.m_269130_();
@@ -67,6 +_,19 @@
} else {
return super.m_7933_(p_193987_, p_193988_, p_193989_);
}
+ }
+
+ @Override
+ public boolean m_7920_(int keyCode, int scanCode, int modifiers) {
+ // Forge: We wait for a second key above if the first press is a modifier
+ // but if they release the modifier then set it explicitly.
+ var key = InputConstants.m_84827_(keyCode, scanCode);
+ if (this.f_193975_ != null && this.f_193975_.getKey() == key) {
+ this.f_193975_ = null;
+ this.f_193976_ = Util.m_137550_();
+ this.f_193977_.m_269130_();
+ }
+ return super.m_7920_(keyCode, scanCode, modifiers);
}
public void m_88315_(GuiGraphics p_282556_, int p_193992_, int p_193993_, float p_193994_) {
@@ -3,12 +3,12 @@
@@ -90,6 +_,7 @@
int i = this.f_97735_;
int j = this.f_97736_;
super.m_88315_(p_283479_, p_283661_, p_281248_, p_281886_);
this.m_7286_(p_283479_, p_281886_, p_283661_, p_281248_);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ContainerScreenEvent.Render.Background(this, p_283479_, p_283661_, p_281248_));
RenderSystem.disableDepthTest();
super.m_88315_(p_283479_, p_283661_, p_281248_, p_281886_);
p_283479_.m_280168_().m_85836_();
p_283479_.m_280168_().m_252880_((float)i, (float)j, 0.0F);
@@ -106,12 +_,13 @@
@@ -107,12 +_,13 @@
int l = slot.f_40220_;
int i1 = slot.f_40221_;
if (this.f_97734_.m_280329_()) {
@@ -23,7 +23,7 @@
ItemStack itemstack = this.f_97711_.m_41619_() ? this.f_97732_.m_142621_() : this.f_97711_;
if (!itemstack.m_41619_()) {
int l1 = 8;
@@ -153,13 +_,16 @@
@@ -149,13 +_,16 @@
}
public static void m_280359_(GuiGraphics p_283692_, int p_281453_, int p_281915_, int p_283504_) {
@@ -42,7 +42,7 @@
}
}
@@ -172,7 +_,8 @@
@@ -168,7 +_,8 @@
p_282567_.m_280168_().m_85836_();
p_282567_.m_280168_().m_252880_(0.0F, 0.0F, 232.0F);
p_282567_.m_280480_(p_281330_, p_281772_, p_281689_);
@@ -52,7 +52,7 @@
p_282567_.m_280168_().m_85849_();
}
@@ -274,7 +_,8 @@
@@ -270,7 +_,8 @@
if (super.m_6375_(p_97748_, p_97749_, p_97750_)) {
return true;
} else {
@@ -62,7 +62,7 @@
Slot slot = this.m_97744_(p_97748_, p_97749_);
long i = Util.m_137550_();
this.f_97723_ = this.f_97709_ == slot && i - this.f_97721_ < 250L && this.f_97722_ == p_97750_;
@@ -285,6 +_,7 @@
@@ -281,6 +_,7 @@
int j = this.f_97735_;
int k = this.f_97736_;
boolean flag1 = this.m_7467_(p_97748_, p_97749_, j, k, p_97750_);
@@ -70,7 +70,7 @@
int l = -1;
if (slot != null) {
l = slot.f_40219_;
@@ -310,7 +_,7 @@
@@ -306,7 +_,7 @@
}
} else if (!this.f_97738_) {
if (this.f_97732_.m_142621_().m_41619_()) {
@@ -79,7 +79,7 @@
this.m_6597_(slot, l, p_97750_, ClickType.CLONE);
} else {
boolean flag2 = l != -999 && (InputConstants.m_84830_(Minecraft.m_91087_().m_91268_().m_85439_(), 340) || InputConstants.m_84830_(Minecraft.m_91087_().m_91268_().m_85439_(), 344));
@@ -334,7 +_,7 @@
@@ -330,7 +_,7 @@
this.f_97717_ = 0;
} else if (p_97750_ == 1) {
this.f_97717_ = 1;
@@ -88,7 +88,7 @@
this.f_97717_ = 2;
}
}
@@ -403,10 +_,13 @@
@@ -399,10 +_,13 @@
}
public boolean m_6348_(double p_97812_, double p_97813_, int p_97814_) {
@@ -102,7 +102,7 @@
int k = -1;
if (slot != null) {
k = slot.f_40219_;
@@ -420,7 +_,7 @@
@@ -416,7 +_,7 @@
if (m_96638_()) {
if (!this.f_97724_.m_41619_()) {
for(Slot slot2 : this.f_97732_.f_38839_) {
@@ -111,7 +111,7 @@
this.m_6597_(slot2, slot2.f_40219_, p_97814_, ClickType.QUICK_MOVE);
}
}
@@ -483,7 +_,7 @@
@@ -479,7 +_,7 @@
this.m_6597_((Slot)null, -999, AbstractContainerMenu.m_38930_(2, this.f_97717_), ClickType.QUICK_CRAFT);
} else if (!this.f_97732_.m_142621_().m_41619_()) {
@@ -120,7 +120,7 @@
this.m_6597_(slot, k, p_97814_, ClickType.CLONE);
} else {
boolean flag1 = k != -999 && (InputConstants.m_84830_(Minecraft.m_91087_().m_91268_().m_85439_(), 340) || InputConstants.m_84830_(Minecraft.m_91087_().m_91268_().m_85439_(), 344));
@@ -530,34 +_,39 @@
@@ -526,34 +_,39 @@
}
public boolean m_7933_(int p_97765_, int p_97766_, int p_97767_) {
@@ -167,7 +167,7 @@
this.m_6597_(this.f_97734_, this.f_97734_.f_40219_, i, ClickType.SWAP);
return true;
}
@@ -592,6 +_,18 @@
@@ -588,6 +_,18 @@
public T m_6262_() {
return this.f_97732_;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
@@ -79,6 +_,8 @@
@@ -74,6 +_,8 @@
private boolean f_98515_;
private final Set<TagKey<Item>> f_98516_ = new HashSet<>();
private final boolean f_256872_;
@@ -9,7 +9,7 @@
public CreativeModeInventoryScreen(Player p_259788_, FeatureFlagSet p_260074_, boolean p_259569_) {
super(new CreativeModeInventoryScreen.ItemPickerMenu(p_259788_), p_259788_.m_150109_(), CommonComponents.f_237098_);
@@ -112,7 +_,7 @@
@@ -107,7 +_,7 @@
private void m_257687_(Collection<ItemStack> p_261591_) {
int i = this.f_97732_.m_257485_(this.f_98508_);
(this.f_97732_).f_98639_.clear();
@@ -18,7 +18,7 @@
this.m_98630_();
} else {
(this.f_97732_).f_98639_.addAll(p_261591_);
@@ -266,6 +_,34 @@
@@ -263,6 +_,34 @@
protected void m_7856_() {
if (this.f_96541_.f_91072_.m_105290_()) {
super.m_7856_();
@@ -53,7 +53,7 @@
this.f_98510_ = new EditBox(this.f_96547_, this.f_97735_ + 82, this.f_97736_ + 6, 80, 9, Component.m_237115_("itemGroup.search"));
this.f_98510_.m_94199_(50);
this.f_98510_.m_94182_(false);
@@ -311,7 +_,7 @@
@@ -308,7 +_,7 @@
public boolean m_5534_(char p_98521_, int p_98522_) {
if (this.f_98514_) {
return false;
@@ -62,7 +62,7 @@
return false;
} else {
String s = this.f_98510_.m_94155_();
@@ -329,7 +_,7 @@
@@ -326,7 +_,7 @@
public boolean m_7933_(int p_98547_, int p_98548_, int p_98549_) {
this.f_98514_ = false;
@@ -71,7 +71,7 @@
if (this.f_96541_.f_91066_.f_92098_.m_90832_(p_98547_, p_98548_)) {
this.f_98514_ = true;
this.m_98560_(CreativeModeTabs.m_258007_());
@@ -364,6 +_,7 @@
@@ -361,6 +_,7 @@
}
private void m_98630_() {
@@ -79,7 +79,7 @@
(this.f_97732_).f_98639_.clear();
this.f_98516_.clear();
String s = this.f_98510_.m_94155_();
@@ -373,10 +_,10 @@
@@ -370,10 +_,10 @@
SearchTree<ItemStack> searchtree;
if (s.startsWith("#")) {
s = s.substring(1);
@@ -92,7 +92,7 @@
}
(this.f_97732_).f_98639_.addAll(searchtree.m_6293_(s.toLowerCase(Locale.ROOT)));
@@ -408,7 +_,8 @@
@@ -405,7 +_,8 @@
protected void m_280003_(GuiGraphics p_283168_, int p_281774_, int p_281466_) {
if (f_98507_.m_40789_()) {
@@ -102,7 +102,7 @@
}
}
@@ -418,7 +_,7 @@
@@ -415,7 +_,7 @@
double d0 = p_98531_ - (double)this.f_97735_;
double d1 = p_98532_ - (double)this.f_97736_;
@@ -111,7 +111,7 @@
if (this.m_98562_(creativemodetab, d0, d1)) {
return true;
}
@@ -439,7 +_,7 @@
@@ -436,7 +_,7 @@
double d1 = p_98623_ - (double)this.f_97736_;
this.f_98509_ = false;
@@ -120,7 +120,7 @@
if (this.m_98562_(creativemodetab, d0, d1)) {
this.m_98560_(creativemodetab);
return true;
@@ -457,6 +_,7 @@
@@ -454,6 +_,7 @@
private void m_98560_(CreativeModeTab p_98561_) {
CreativeModeTab creativemodetab = f_98507_;
f_98507_ = p_98561_;
@@ -128,7 +128,7 @@
this.f_97737_.clear();
(this.f_97732_).f_98639_.clear();
this.m_238391_();
@@ -533,13 +_,15 @@
@@ -530,13 +_,15 @@
this.f_98511_ = null;
}
@@ -145,8 +145,8 @@
this.m_98630_();
} else {
@@ -595,7 +_,7 @@
public void m_88315_(GuiGraphics p_283000_, int p_281317_, int p_282770_, float p_281295_) {
@@ -593,7 +_,7 @@
this.m_280273_(p_283000_);
super.m_88315_(p_283000_, p_281317_, p_282770_, p_281295_);
- for(CreativeModeTab creativemodetab : CreativeModeTabs.m_257388_()) {
@@ -154,7 +154,7 @@
if (this.m_280537_(p_283000_, creativemodetab, p_281317_, p_282770_)) {
break;
}
@@ -605,13 +_,22 @@
@@ -603,13 +_,22 @@
p_283000_.m_280557_(this.f_96547_, f_98506_, p_281317_, p_282770_);
}
@@ -178,7 +178,7 @@
TooltipFlag.Default tooltipflag$default = this.f_96541_.f_91066_.f_92125_ ? TooltipFlag.Default.f_256730_ : TooltipFlag.Default.f_256752_;
TooltipFlag tooltipflag = flag ? tooltipflag$default.m_257777_() : tooltipflag$default;
List<Component> list = p_281769_.m_41651_(this.f_96541_.f_91074_, tooltipflag);
@@ -631,7 +_,7 @@
@@ -629,7 +_,7 @@
int i = 1;
for(CreativeModeTab creativemodetab : CreativeModeTabs.m_257388_()) {
@@ -187,7 +187,7 @@
list1.add(i++, creativemodetab.m_40786_().m_6881_().m_130940_(ChatFormatting.BLUE));
}
}
@@ -641,13 +_,13 @@
@@ -639,21 +_,22 @@
}
protected void m_7286_(GuiGraphics p_282663_, float p_282504_, int p_282089_, int p_282249_) {
@@ -203,15 +203,17 @@
this.f_98510_.m_88315_(p_282663_, p_282089_, p_282249_, p_282504_);
int j = this.f_97735_ + 175;
int k = this.f_97736_ + 18;
@@ -657,6 +_,7 @@
p_282663_.m_292816_(resourcelocation, j, k + (int)((float)(i - k - 17) * this.f_98508_), 12, 15);
int i = k + 112;
if (f_98507_.m_40791_()) {
- p_282663_.m_280218_(f_98504_, j, k + (int)((float)(i - k - 17) * this.f_98508_), 232 + (this.m_98631_() ? 0 : 12), 0, 12, 15);
+ p_282663_.m_280218_(f_98507_.getTabsImage(), j, k + (int)((float)(i - k - 17) * this.f_98508_), 232 + (this.m_98631_() ? 0 : 12), 0, 12, 15);
}
+ if (currentPage.getVisibleTabs().contains(f_98507_)) //Forge: only display tab selection when the selected tab is on the current page
this.m_280560_(p_282663_, f_98507_);
if (f_98507_.m_257962_() == CreativeModeTab.Type.INVENTORY) {
InventoryScreen.m_274545_(p_282663_, this.f_97735_ + 73, this.f_97736_ + 6, this.f_97735_ + 105, this.f_97736_ + 49, 20, 0.0625F, (float)p_282089_, (float)p_282249_, this.f_96541_.f_91074_);
@@ -665,7 +_,7 @@
InventoryScreen.m_274545_(p_282663_, this.f_97735_ + 88, this.f_97736_ + 45, 20, (float)(this.f_97735_ + 88 - p_282089_), (float)(this.f_97736_ + 45 - 30 - p_282249_), this.f_96541_.f_91074_);
@@ -662,7 +_,7 @@
}
private int m_258094_(CreativeModeTab p_260136_) {
@@ -220,7 +222,7 @@
int j = 27;
int k = 27 * i;
if (p_260136_.m_6563_()) {
@@ -677,7 +_,7 @@
@@ -674,7 +_,7 @@
private int m_257995_(CreativeModeTab p_260181_) {
int i = 0;
@@ -229,7 +231,7 @@
i -= 32;
} else {
i += this.f_97727_;
@@ -705,8 +_,8 @@
@@ -702,8 +_,8 @@
protected void m_280560_(GuiGraphics p_283590_, CreativeModeTab p_283489_) {
boolean flag = p_283489_ == f_98507_;
@@ -237,18 +239,20 @@
- int i = p_283489_.m_257903_();
+ boolean flag1 = currentPage.isTop(p_283489_);
+ int i = currentPage.getColumn(p_283489_);
int j = this.f_97735_ + this.m_258094_(p_283489_);
int k = this.f_97736_ - (flag1 ? 28 : -(this.f_97727_ - 4));
ResourceLocation[] aresourcelocation;
@@ -716,6 +_,7 @@
aresourcelocation = flag ? f_291557_ : f_291303_;
int j = i * 26;
int k = 0;
int l = this.f_97735_ + this.m_258094_(p_283489_);
@@ -720,7 +_,8 @@
i1 += this.f_97727_ - 4;
}
- p_283590_.m_280218_(f_98504_, l, i1, j, k, 26, 32);
+ com.mojang.blaze3d.systems.RenderSystem.enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
p_283590_.m_292816_(aresourcelocation[Mth.m_14045_(i, 0, aresourcelocation.length)], j, k, 26, 32);
+ p_283590_.m_280218_(p_283489_.getTabsImage(), l, i1, j, k, 26, 32);
p_283590_.m_280168_().m_85836_();
p_283590_.m_280168_().m_252880_(0.0F, 0.0F, 100.0F);
@@ -759,6 +_,14 @@
l += 5;
@@ -763,6 +_,14 @@
}
@@ -263,7 +267,7 @@
@OnlyIn(Dist.CLIENT)
static class CustomCreativeSlot extends Slot {
public CustomCreativeSlot(Container p_98633_, int p_98634_, int p_98635_, int p_98636_) {
@@ -926,6 +_,22 @@
@@ -930,6 +_,22 @@
public boolean m_8010_(Player p_98665_) {
return this.f_98655_.m_8010_(p_98665_);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
@@ -45,12 +_,17 @@
@@ -41,12 +_,17 @@
Collection<MobEffectInstance> collection = this.f_96541_.f_91074_.m_21220_();
if (!collection.isEmpty() && j >= 32) {
boolean flag = j >= 120;
@@ -19,7 +19,7 @@
this.m_280172_(p_281945_, i, k, iterable, flag);
this.m_280301_(p_281945_, i, k, iterable, flag);
if (flag) {
@@ -96,6 +_,11 @@
@@ -92,6 +_,11 @@
int i = this.f_97736_;
for(MobEffectInstance mobeffectinstance : p_282642_) {
@@ -31,7 +31,7 @@
MobEffect mobeffect = mobeffectinstance.m_19544_();
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.m_118732_(mobeffect);
p_282745_.m_280159_(p_282521_ + (p_281536_ ? 6 : 7), i + 7, 0, 18, 18, textureatlassprite);
@@ -108,6 +_,11 @@
@@ -104,6 +_,11 @@
int i = this.f_97736_;
for(MobEffectInstance mobeffectinstance : p_281986_) {
@@ -1,15 +1,15 @@
--- a/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
@@ -93,7 +_,7 @@
@@ -88,7 +_,7 @@
int l1 = 86 - this.f_96547_.m_92895_(s);
FormattedText formattedtext = EnchantmentNames.m_98734_().m_98737_(this.f_96547_, l1);
int i2 = 6839882;
- if ((k < l + 1 || this.f_96541_.f_91074_.f_36078_ < k1) && !this.f_96541_.f_91074_.m_150110_().f_35937_) {
+ if (((k < l + 1 || this.f_96541_.f_91074_.f_36078_ < k1) && !this.f_96541_.f_91074_.m_150110_().f_35937_) || this.f_97732_.f_39447_[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels
p_282430_.m_292816_(f_291504_, i1, j + 14 + 19 * l, 108, 19);
p_282430_.m_292816_(f_291094_[l], i1 + 1, j + 15 + 19 * l, 16, 16);
p_282430_.m_280218_(f_98747_, i1, j + 14 + 19 * l, 0, 185, 108, 19);
p_282430_.m_280218_(f_98747_, i1 + 1, j + 15 + 19 * l, 16 * l, 239, 16, 16);
p_282430_.m_280554_(this.f_96547_, formattedtext, j1, j + 16 + 19 * l, l1, (i2 & 16711422) >> 1);
@@ -154,10 +_,13 @@
@@ -150,10 +_,13 @@
Enchantment enchantment = Enchantment.m_44697_((this.f_97732_).f_39447_[j]);
int l = (this.f_97732_).f_39448_[j];
int i1 = j + 1;
@@ -0,0 +1,16 @@
--- a/net/minecraft/client/gui/screens/inventory/InventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/InventoryScreen.java
@@ -93,6 +_,13 @@
public static void m_274545_(GuiGraphics p_282802_, int p_275688_, int p_275245_, int p_275535_, float p_275604_, float p_275546_, LivingEntity p_275689_) {
float f = (float)Math.atan((double)(p_275604_ / 40.0F));
float f1 = (float)Math.atan((double)(p_275546_ / 40.0F));
+ // Forge: Allow passing in direct angle components instead of mouse position
+ renderEntityInInventoryFollowsAngle(p_282802_, p_275688_, p_275245_, p_275535_, f, f1, p_275689_);
+ }
+
+ public static void renderEntityInInventoryFollowsAngle(GuiGraphics p_282802_, int p_275688_, int p_275245_, int p_275535_, float angleXComponent, float angleYComponent, LivingEntity p_275689_) {
+ float f = angleXComponent;
+ float f1 = angleYComponent;
Quaternionf quaternionf = (new Quaternionf()).rotateZ((float)Math.PI);
Quaternionf quaternionf1 = (new Quaternionf()).rotateX(f1 * 20.0F * ((float)Math.PI / 180F));
quaternionf.mul(quaternionf1);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
@@ -236,7 +_,12 @@
@@ -229,7 +_,12 @@
p_281357_.m_280370_(this.f_96547_, p_283466_, p_282403_, p_283601_);
} else {
p_281357_.m_280302_(this.f_96547_, p_282046_, p_282403_, p_283601_, p_282046_.m_41613_() == 1 ? "1" : null);
@@ -13,4 +13,4 @@
+ p_281357_.m_280168_().m_85849_();
p_281357_.m_280168_().m_85836_();
p_281357_.m_280168_().m_252880_(0.0F, 0.0F, 300.0F);
p_281357_.m_295520_(f_291695_, p_282403_ + 7, p_283601_ + 12, 0, 9, 2);
p_281357_.m_280398_(f_99113_, p_282403_ + 7, p_283601_ + 12, 0, 0.0F, 176.0F, 9, 2, 512, 256);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/multiplayer/JoinMultiplayerScreen.java
+++ b/net/minecraft/client/gui/screens/multiplayer/JoinMultiplayerScreen.java
@@ -281,6 +_,11 @@
@@ -283,6 +_,11 @@
}
Loaded 100 of 470 files, more files were not shown because too many files have changed in this diff. Show more