Compare commits

..
69 Commits
Author SHA1 Message Date
LexManos 9ccfaf4812 1.21.5 RB 1 2025-08-27 12:02:50 -07:00
Paint_Ninja 3ed3d2b9cf Update to EventBus 6.2.32 (#10644)
- Performance improvements, especially for posting to zero or one listeners on an event
- New Event#cancel() convenience method
- Only the monitor priority is tracked on the Forge bus now
2025-08-27 17:36:13 +01:00
Matt 3d374fe732 [1.21.5] Add ForgeLayeredDraw & ModifyOverlayLayersEvent as API to making gui layers. (#10556) 2025-07-25 10:44:49 -07:00
Paint_Ninja a02f3f9841 Update MDK to fix OOM error and aid getting Mixin setup (#10559) 2025-06-09 22:19:37 +01:00
LexManos c5e462f7d2 Remove legacy patch that caused tripwires to create a loop. Fixes #10558 2025-06-01 00:43:08 -07:00
Matt d1f79d6655 Fix warped and crimson fungi not being able to be placed on nylium. (#10544)
Fix other PlantType parity issues, add test for all vanilla PlantType blocks.
Co-authored-by: LexManos <[email protected]>
2025-05-23 02:22:26 -07:00
LexManos 9d5e81b1a9 Fix modded keybidings being reset to default when reloading. Fixes: #10531 2025-05-22 00:40:04 -07:00
LexManos a1c275df46 Deprecate GatherDataEvent.validate() as validation always happens. And made ExistingFileHelper always function. Closes #10516 2025-05-21 23:42:44 -07:00
LexManos 4ef7fe8bd8 Call getToolModifiedState for AXE_STRIP and AXE_WAX_OFF. 2025-05-21 23:41:54 -07:00
LexManos ce8838e721 Fix Wood Stripping sound not playing. Fixes #10525 2025-05-20 23:12:19 -07:00
LexManos b7e2593d48 Fix dedicated server not loading default language files. Fixes #10555 2025-05-16 13:01:02 -07:00
Joseph T. McQuigg 33d177f02e Make Loot Function without builders Constructors public (#10521) 2025-05-14 21:17:58 -07:00
Olivier Sechet 5d2186df63 Ensure changes from keyboard in ForgeSlider behave as changes from mouse (#10554) 2025-05-09 15:14:16 -07:00
LexManos 77af36b807 Add YourKit mention 2025-05-08 13:40:26 -07:00
Matt 54eeca0aed Fix creative inventory not displaying item categories correctly. Fixes #10524 2025-05-05 14:54:16 -07:00
LexManos 3de0566425 Make unbound tags non-fatal due to Mojang's registry loading order issues. Closes #10524 2025-05-05 14:52:43 -07:00
LexManos a5ebf3b645 Fix PlayerEquipmentInvWrapper offset. Closes #10532 2025-05-05 12:13:58 -07:00
Paint_Ninja 63d0496cc4 Deprecate DistExecutor for removal (#10198) 2025-04-23 20:54:22 +01:00
Paint_Ninja 31f623e794 Cleanup early display's internals a bit more (#10538) 2025-04-23 20:53:29 +01:00
Erizamanu eb001a6382 Add ChunkEvent.LightingCalculated, fixes #8354 (#10533) 2025-04-22 21:11:26 +01:00
Paint_Ninja 504dcad849 Seal most event hierarchies (#10515)
Most events in Forge are not designed to be extended by mod devs but technically allowed it before this PR, leading to a risk of unintentional breaking changes for those that do.

If you need to extend a Forge event, please let us know so that we can explicitly support that and design it with extending in mind. Note that this change does not affect making your own events that directly extend from EventBus' `Event` class.
2025-04-19 13:18:48 +01:00
Matt 81f7f029c3 Fix NPE when breeze deflects a projectile (#10535) 2025-04-19 13:08:10 +01:00
Jonathing 207c1997c9 Fix Swords and Pickaxes not using ToolActions (#10520) 2025-04-06 12:08:21 -05:00
LexManos e348ae5b84 Fix bundles causing crash upon inserting item. Closes #10509 2025-03-27 22:09:50 -07:00
LexManos 0f3b8ee830 Add DeferredRegistryData to help with generating data driven registry entries.
Revive GameTest system and make all but one Forge Test mod pass.
2025-03-27 20:52:35 -07:00
LexManos b4b6e48a7a Fix Mod List Screen's render layout and scroll bars. 2025-03-26 18:54:11 -07:00
d50a3b5ab7 Minecraft 1.21.5
Co-authored-by: Ven <[email protected]>
Co-authored-by: Jonathing <[email protected]>
2025-03-26 16:34:26 -07:00
Joseph T. McQuigg 88904a1d09 Add Pumpkin Block and Item Tags (#10482) 2025-03-17 00:04:24 +00:00
Jonathing b864faf0ef Add '#forge:chorus_additionally_grows_on' tag for similar mechanics to '#minecraft:azalea_grows_on' but for chorus (#10459) 2025-03-04 12:47:17 -08:00
cech12 c97eabc0c4 Fix Hanging Pale Moss not dropping with modded shears (#10414) 2025-02-17 18:06:56 -08:00
Jonathing 6ae39c8597 1.21.4 RB 1
https://forums.minecraftforge.net/topic/154394-forge-541-minecraft-1214/
2025-02-12 12:29:03 -08:00
Jonathing dcafb4f633 Fix corrupted and invalidly symlinked worlds crashing on level select (#10406) 2025-02-12 11:52:53 -08:00
Jonathing 1ea7ce9831 Add fast graphics render type to block model jsons (#10394)
Make modded leaves behave like vanilla leaves by default (Fixes #10389)
2025-02-12 11:47:09 -08:00
Jonathing 674f2efd54 Add updated tag context to AddReloadListenerEvent (#10412)
Fixes using custom tags in GlobalLootModifiers.
2025-02-12 11:02:22 -08:00
Jonathing 02e82c672d Give ItemStack context to IForgeItem.getCapabilityProvider (#10404) 2025-02-05 09:15:37 -08:00
RealMangoRage b25f6e3a7c Re-introduce ItemStack Capabilities (#10324) 2025-02-03 18:44:44 -08:00
LexManos e69b07a54a Fix redstone updates for comparators going up/down incorrectly. Related: #9973 2025-02-03 18:32:53 -08:00
Jonathing 79efe2ac36 Fix forced chunks never being ticked by the server (#10325) 2025-02-03 13:47:36 -08:00
LexManos 464483db5b Fix redstone update order not matching vanilla. (#10392) 2025-02-03 13:36:45 -08:00
LexManos f49adb285f Fix game test structure rotations being inconsistant (#10391) 2025-02-03 13:31:20 -08:00
Jonathing 55862dfd1d Re-introduce IForgeItem.damageItem when an item takes damage, Fixes #10344 (#10371) 2025-02-03 13:17:38 -08:00
Jonathing 124b9bd8d3 Gate client test mods behind clientSideOnly (#10390) 2025-02-03 13:17:01 -08:00
Jonathing bae3915728 Fix issue with superclass event listeners by updating EventBus (#10384) 2025-02-03 11:13:33 -08:00
Jonathing b3c2c62c7e Bump dependencies, most notably EventBus (#10370)
- CoreMods 5.2.4 -> 5.2.6
- EventBus 6.2.15 -> 6.2.26
    - Reduced memory usage
    - Further performance improvements
    - Fixed EventBus#39, unregistered listeners are now immediately reclaimable by the GC
- Apache MavenArtifact 3.8.5 -> 3.8.8
- NightConfig 3.7.3 -> 3.7.4
2025-01-28 21:00:16 +00:00
Jonathing 68698d70c1 Fix shield disabling being completely ignored (#10316) 2025-01-27 15:24:30 -08:00
Jonathing d55dee9394 Update Gradle to 8.12.1 2025-01-27 09:17:02 -08:00
Jonathing 2d114f2719 Fix JOpt Simple by updating ModLauncher (#10347) 2025-01-27 09:16:24 -08:00
JonathingandLexManos 3e6583af01 GameTestHelper additions (#10338)
Co-authored-by: LexManos <[email protected]>
2025-01-27 09:15:57 -08:00
Paint_NinjaandTelepathicGrunt 762f6a7d78 Add c:flowers, c:flowers/tall, and c:flowers/small block and item tags (#10335)
Co-authored-by: TelepathicGrunt <[email protected]>
2025-01-25 20:55:58 +00:00
Jonathing 3c5a534b7a Fix JOpt Simple needing a strict version requirement declaration (#10311) 2025-01-25 17:49:11 +00:00
Jonathing bc62d1693a Fix incorrect method reference in TntBlock.explode() (#10326) 2025-01-25 17:48:54 +00:00
Joseph T. McQuigg 554ead8d4a Fix issues in VillagerTrades.EmeraldsForVillagerTypeItem related to custom Villager Types (#10298)
Add VillagerType#registerBiomeType
2025-01-21 16:07:56 -08:00
LexManos ec5ac91389 Fix render_type in block models not being used. Fixes #10294 2025-01-13 13:27:47 -08:00
Jonathing f63813d929 Bump dependencies (#10274)
- EventBus 6.2.8 -> 6.2.15
- Bootstrap 2.1.7 -> 2.1.8
- SecureModules 2.2.20 -> 2.2.21
- AccessTransformers 8.2.0 -> 8.2.1
- ModLauncher 10.2.2 -> 10.2.3
These bumps include further clean-up and optimisations.
2025-01-04 16:04:31 +00:00
Jonathing 5d4825ac4b Simplify Title Screen Brandings (#10287) 2025-01-02 14:31:05 -08:00
Jonathing 3024ef7707 Clean and fix Forge's internal coremods, fixes finalizeSpawn hook. (#10271) 2024-12-30 11:18:20 -08:00
Gabriel Harris-Rouquette 0d3b488728 Update jline for better darwin/arm64 support Fixes #10107 (#10279) 2024-12-29 09:25:21 -08:00
Jonathing a01012f20c Bump CoreMods to 5.2.4 (#10262) 2024-12-23 15:25:21 -08:00
Jonathing d4e3ef4a22 Allow mipmap lowering to be disabled (#10242) 2024-12-23 11:46:59 -08:00
Jonathing d7293a78dc Manage FileWatcher instance per ConfigFileTypeHandler (#10213) 2024-12-22 11:59:00 -08:00
Paint_Ninja 8e4e02e258 Skip processing Forge classes in RuntimeDistCleaner (#10199)
Mod classes are still transformed as usual
2024-12-21 22:20:21 +00:00
Paint_Ninja 2f5a6fee48 Skip Forge classes in the RuntimeEnumExtender transformer (#10197)
Mod classes are still transformed as usual
2024-12-21 22:19:07 +00:00
LexManos 0e74886f8d Add hooks for using Vanilla's new Client data generator (#10206)
Add new hook for custom block models that do not have real blocks backing them
Some workspace cleanup fixing log4j annotation processor
2024-12-19 10:41:21 -08:00
Paint_Ninja 07977ba242 Deprecate @ObjectHolder, add a couple of fast-paths (#10195) 2024-12-06 18:18:53 +00:00
LexManos a894c244fe Bump Bootstrap which has a slight performance boost during dev time. 2024-12-06 10:13:49 -08:00
LexManos cf32a799a4 Speed up mod annotation scanning by ~30% 2024-12-06 10:11:04 -08:00
Paint_Ninja 0fda1d9393 Skip Vanilla classes for the CapabilityTokenSubclass transformer (#10196) 2024-12-06 17:35:09 +00:00
Paint_NinjaandTelepathicGrunt c7f0acbe38 Simplify memory usage display on loading screen (#10193)
Co-authored-by: TelepathicGrunt <[email protected]>
2024-12-06 17:34:33 +00:00
LexManos 9c06c20023 Fix custom particles causing crash 2024-12-05 16:40:29 -08:00
930 changed files with 13191 additions and 8623 deletions

No files matched your search

+1
View File
@@ -3,6 +3,7 @@
*.patch text eol=lf
*.java text eol=lf
*.gradle text eol=crlf
**/MANIFEST.MF text eol=crlf
*.png binary
*.gif binary
*.exe binary
+5
View File
@@ -41,3 +41,8 @@ src/*/generated/**/.cache/
/ForgeRoot.ipr
/ForgeRoot.iws
# APT stuff
/*/.gitignore
/*/.factorypath
/*/.apt_generated/
@@ -3,6 +3,7 @@ package net.minecraftforge.forge.tasks
import groovy.transform.CompileStatic
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Internal
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodNode
@@ -12,13 +13,19 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
@Internal
abstract Property<Closure<Boolean>> getPredicate()
private final Set<String> matches = new HashSet<>()
private final Map<String, List<String>> matches = new TreeMap<>(Comparator.naturalOrder())
@Override
protected process(ClassNode parent, MethodNode node) {
for (final current : node.instructions) {
if (predicate.get().call(parent, node, current)) {
matches.add(parent.name)
var methods = matches.compute(parent.name, { k, v -> v ?: new ArrayList<>() })
// only add non-synthetic methods
if ((node.access & Opcodes.ACC_SYNTHETIC) == 0) {
methods.add(node.name + node.desc)
}
return
}
}
@@ -27,6 +34,15 @@ 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.')}()
var array = new ArrayList<Object>()
matches.forEach { c, m ->
{
array.add(
'class': c,
'methods': m
)
}
}
return array ?: { throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.') }()
}
}
+48 -18
View File
@@ -92,18 +92,18 @@ final String MAVEN_PATH = ext.MAVEN_PATH
final String BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.2.0:fatjar'
final String INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.3'
final String FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.6'
final String S2S_TOOL = 'net.minecraftforge:Srg2Source:8.1.0:fatjar'
final String S2S_TOOL = 'net.minecraftforge:Srg2Source:8.1.1:fatjar'
configurations {
// Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
bootstrap { transitive = false }
installer {
installer {
extendsFrom(bootstrap)
transitive = false
transitive = false
}
installerextra {
installerextra {
extendsFrom(bootstrap)
transitive = false
transitive = false
}
api.extendsFrom(installer)
}
@@ -117,9 +117,9 @@ dependencies {
bootstrap(libs.securemodules) // Has Union file system in it
bootstrap(libs.unsafe) // Needed by securemodules
bootstrap(libs.bundles.asm) // Needed by securemodules
implementation(libs.jopt.simple) { version { strictly '5.0.4' } }
implementation(libs.jopt.simple)
installer(libs.bootstrap)
installer(libs.bootstrap.api) // Needed by securemodules
installer(libs.accesstransformers)
@@ -209,7 +209,6 @@ patcher {
'--all',
'--validate',
'--output', rootProject.file('src/main/generated/'),
'--validate',
'--existing', sourceSets.main.resources.srcDirs[0],
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
@@ -227,6 +226,30 @@ patcher {
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
forge_client_data {
args '--launchTarget', 'forge_dev_client_data',
'--mod', 'forge',
'--all',
'--output', rootProject.file('src/main/generated/'),
'--existing', sourceSets.main.resources.srcDirs[0],
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
forge_client_data_test {
source sourceSets.test
args '--launchTarget', 'forge_dev',
'--launchEntry', 'minecraft/net.minecraft.client.data.Main',
'--launchData',
'--mod', '.+',
'--all',
'--output', rootProject.file('src/test/generated/'),
'--existing', sourceSets.main.resources.srcDirs[0],
'--existing', sourceSets.test.resources.srcDirs[0],
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
}
}
@@ -268,11 +291,11 @@ tasks.register('downloadCrowdin', Download) {
tasks.userdevConfig.configure {
configurations.installer.allDependencies.forEach {
def dep = it.toString()
if (it instanceof ProjectDependency)
if (it instanceof ProjectDependency)
dep = "net.minecraftforge:$it.dependencyProject.name:$it.dependencyProject.version"
libraries.add(dep)
}
inject = '' // We don't have a userdev sourceset anymore. Empty as a gradle workaround...
runs {
client {
@@ -284,6 +307,13 @@ tasks.userdevConfig.configure {
args '--assetsDir', '{assets_root}'
}
clientData {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
args '--launchTarget', "forge_userdev_client_data"
args '--assetIndex', '{asset_index}'
args '--assetsDir', '{assets_root}'
}
server {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
property 'forge.enableGameTest', 'true'
@@ -381,13 +411,13 @@ tasks.register('extractInheritance', ExtractInheritance) {
}
}
tasks.register("findFinalizeSpawnTargets", BytecodePredicateFinder) {
jar = createJoinedSRG.output
jar = createClientOfficial.output
output = rootProject.file('src/main/resources/coremods/finalize_spawn_targets.json')
predicate = {
parent, node, insn ->
return 'net/minecraft/world/level/BaseSpawner' != parent.name // Ignore this class as we special case it.
&& insn.getOpcode().equals(Opcodes.INVOKEVIRTUAL)
&& insn.name == 'm_6518_'
&& insn.name == 'finalizeSpawn'
&& insn.desc == '(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;';
}
}
@@ -493,7 +523,7 @@ tasks.register('serverShimJar', Jar) {
from {
zipTree(downloadServerShim.output).find { it.name == 'MANIFEST.MF' }
}
attributes('Class-Path': configurations.bootstrap.resolvedConfiguration.resolvedArtifacts.collect { "libraries/${Util.getMavenInfoFromDep(it).path}" }.join(' '))
}
archiveClassifier = 'shim'
@@ -586,7 +616,7 @@ tasks.register('checkJarCompatibility', CheckJarCompatibility) {
baseLibraries.from(project.tasks.named('createJoinedSRG').flatMap { it.output })
inputJar = project.tasks.named('reobfJar').flatMap { it.output }
commonLibraries.from(project.configurations.minecraftImplementation)
commonLibraries.from(project.configurations.installer)
}
@@ -607,11 +637,11 @@ tasks.register('launcherJson', LauncherJson).configure {
tasks.register('installerJson', InstallerJson) {
icon = rootProject.file('icon.ico')
// Json to install into the client's launcher
dependsOn(launcherJson)
input.from(launcherJson.output)
// Download Official Mappings
dependsOn(downloadClientMappings, downloadServerMappings)
input.from(downloadClientMappings.output, downloadServerMappings.output)
@@ -1059,7 +1089,7 @@ publishing {
license gradleutils.pom.Licenses.LGPLv2_1
}
}
repositories {
maven gradleutils.publishingForgeMaven
}
+1 -1
View File
@@ -44,7 +44,7 @@ tasks.withType(JavaCompile).configureEach {
dependsOn 'processResources' // Needed because we merge the output of this with the output of the compile task. And gradle detects downstream tasks using the output without a hard dep
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
options.warnings = false // Shutup deprecated for removal warnings
options.forkOptions.jvmArgs += '-Xmx3G' // Needed to make compiling faster, and not run out of heap space in some cases.
options.forkOptions.jvmArgs += '-Xmx6G' // Needed to make compiling faster, and not run out of heap space in some cases.
}
// Merge the resources and classes into the same directory. We'll need to split them at runtime because
+31 -6
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.6-&query=$.promos["1.20.6-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.6-&query=$.promos["1.20.6-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.21.5-&query=$.promos["1.21.5-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.21.5-&query=$.promos["1.21.5-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]
@@ -31,6 +30,19 @@ You can download the installer for the *Recommended Build* or the
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].
@@ -58,13 +70,25 @@ Please ensure you have a valid email address associated with your GitHub account
to use and modify. However, it costs money to run such a large project as this, so please consider
[becoming a patron][Patreon].*
### Thanks
[![YourKit](https://www.yourkit.com/images/yklogo.png)](https://www.yourkit.com/)
YourKit for providing us accesss to their [YourKit Java Profiler] which helps identify bottlenecks and places for improvment.
[Contributing]: ./CONTRIBUTING.md
[CLA]: https://cla-assistant.io/MinecraftForge/MinecraftForge
[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/
@@ -74,3 +98,4 @@ Please ensure you have a valid email address associated with your GitHub account
[Pull-Requests]: https://docs.minecraftforge.net/en/latest/forgedev/#making-changes-and-pull-requests
[Patreon]: https://www.patreon.com/LexManos
[YourKit Java Profiler]: https://www.yourkit.com/java/profiler/
@@ -25,7 +25,18 @@ import java.util.function.Supplier;
* <li>When you want to call one thing on one side, another thing on the other and return a result {@link #safeRunForDist(Supplier, Supplier)}</li>
* <li>When you want to run something on one side {@link #safeRunWhenOn(Dist, Supplier)}</li>
* </ul>
*
* @deprecated Historically, this allowed for safe execution of code on the correct side by exploiting a low-level
* detail in Java 8, but in newer versions a simple if check is enough.
* <br>
* For example:
* <pre>{@code
* if (FMLEnvironment.dist.isClient()) {
* // client code here
* }
* }</pre>
*/
@Deprecated(since = "1.21.5", forRemoval = true)
public final class DistExecutor
{
private static final Logger LOGGER = LogManager.getLogger();
@@ -14,6 +14,7 @@ import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.loading.FMLConfig;
import net.minecraftforge.fml.loading.FMLPaths;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.io.IOException;
@@ -25,9 +26,66 @@ import static net.minecraftforge.fml.config.ConfigTracker.CONFIG;
public class ConfigFileTypeHandler {
private static final Logger LOGGER = LogUtils.getLogger();
static final ConfigFileTypeHandler TOML = new ConfigFileTypeHandler();
private static final Path defaultConfigPath = FMLPaths.GAMEDIR.get().resolve(FMLConfig.getConfigValue(FMLConfig.ConfigValue.DEFAULT_CONFIG_PATH));
private static final ConfigFileTypeHandler CLIENT = new ConfigFileTypeHandler(ModConfig.Type.CLIENT);
private static final ConfigFileTypeHandler COMMON = new ConfigFileTypeHandler(ModConfig.Type.COMMON);
private static final ConfigFileTypeHandler SERVER = new ConfigFileTypeHandler(ModConfig.Type.SERVER);
private final @Nullable ModConfig.Type type;
private @Nullable FileWatcher watcher;
// exists for bin compat
public ConfigFileTypeHandler() {
this(null);
}
private ConfigFileTypeHandler(@Nullable ModConfig.Type type) {
this.type = type;
}
/**
* Gets the handler for the given {@link ModConfig.Type}.
*
* @param type The type to get the handler for
* @return The handler
*/
static ConfigFileTypeHandler get(ModConfig.Type type) {
return switch (type) {
case CLIENT -> CLIENT;
case COMMON -> COMMON;
case SERVER -> SERVER;
};
}
/**
* Gets the {@link FileWatcher} for this handler, creating it if it doesn't exist and/or has been stopped.
*
* @return The watcher
*
* @apiNote This is package-private so modders can't just call {@link FileWatcher#stop()} and fuck up everything.
*/
FileWatcher getWatcher() {
if (this.watcher == null) {
LOGGER.debug(CONFIG, "Starting watcher for handler: {}", this);
this.watcher = new FileWatcher();
}
return this.watcher;
}
/**
* Stops the {@link FileWatcher} for this handler, and sets it to null afterward. Use this instead of
* {@link FileWatcher#stop()}.
*/
void stopWatcher() {
if (this.watcher == null) return;
LOGGER.debug(CONFIG, "Stopping watcher for hander: {}", this);
this.watcher.stop();
this.watcher = null;
}
public Function<ModConfig, CommentedFileConfig> reader(Path configBasePath) {
return (c) -> {
final Path configPath = configBasePath.resolve(c.getFileName());
@@ -37,7 +95,7 @@ public class ConfigFileTypeHandler {
onFileNotFound((newfile, configFormat)-> setupConfigFile(c, newfile, configFormat)).
writingMode(WritingMode.REPLACE).
build();
LOGGER.debug(CONFIG, "Built TOML config for {}", configPath.toString());
LOGGER.debug(CONFIG, "Built TOML config for {}", configPath);
try
{
configData.load();
@@ -46,9 +104,9 @@ public class ConfigFileTypeHandler {
{
throw new ConfigLoadingException(c, ex);
}
LOGGER.debug(CONFIG, "Loaded TOML config file {}", configPath.toString());
FileWatcher.defaultInstance().addWatch(configPath, new ConfigWatcher(c, configData, Thread.currentThread().getContextClassLoader()));
LOGGER.debug(CONFIG, "Watching TOML config file {} for changes", configPath.toString());
LOGGER.debug(CONFIG, "Loaded TOML config file {}", configPath);
this.getWatcher().addWatch(configPath, new ConfigWatcher(c, configData, Thread.currentThread().getContextClassLoader()));
LOGGER.debug(CONFIG, "Watching TOML config file {} for changes", configPath);
return configData;
};
}
@@ -56,9 +114,9 @@ public class ConfigFileTypeHandler {
public void unload(Path configBasePath, ModConfig config) {
Path configPath = configBasePath.resolve(config.getFileName());
try {
FileWatcher.defaultInstance().removeWatch(configBasePath.resolve(config.getFileName()));
this.getWatcher().removeWatch(configPath);
} catch (RuntimeException e) {
LOGGER.error("Failed to remove config {} from tracker!", configPath.toString(), e);
LOGGER.error("Failed to remove config {} from tracker!", configPath, e);
}
}
@@ -109,6 +167,11 @@ public class ConfigFileTypeHandler {
}
}
@Override
public String toString() {
return "ConfigFileTypeHandler[" + (type != null ? type : "UNKNOWN") + "]";
}
private record ConfigWatcher(
ModConfig modConfig,
CommentedFileConfig commentedFileConfig,
@@ -8,6 +8,9 @@ package net.minecraftforge.fml.config;
import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.mojang.logging.LogUtils;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.loading.FMLPaths;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
@@ -52,11 +55,24 @@ public class ConfigTracker {
}
}
// TODO: [FML] This is only called for the server (outside of forceUnload)
// rethink config implementation for eventual FML rewrite
public void unloadConfigs(ModConfig.Type type, Path configBasePath) {
LOGGER.debug(CONFIG, "Unloading configs type {}", type);
for (ModConfig config : this.configSets.get(type)) {
closeConfig(config, configBasePath);
}
ConfigFileTypeHandler.get(type).stopWatcher();
}
// If there is a better way to do this, please tell me. Because this is FUCKED
public void forceUnload() {
// This is how ModStateProvider handles loading configs. So we're doing the same but with unloadConfigs instead
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.unloadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get()));
this.unloadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get());
// just in case server watcher is still alive somehow...
ConfigFileTypeHandler.get(ModConfig.Type.SERVER).stopWatcher();
}
private static void openConfig(final ModConfig config, final Path configBasePath) {
@@ -30,7 +30,7 @@ public class ModConfig
this.spec = spec;
this.fileName = fileName;
this.container = container;
this.configHandler = ConfigFileTypeHandler.TOML;
this.configHandler = ConfigFileTypeHandler.get(type);
ConfigTracker.INSTANCE.trackConfig(this);
}
@@ -90,7 +90,12 @@ public class DisplayWindow implements ImmediateWindowProvider {
// The GL ID of the window. Used for all operations
private long window;
// The thread that contains and ticks the window while Forge is loading mods
private ScheduledExecutorService renderScheduler;
private static final ScheduledExecutorService renderScheduler = Executors.newSingleThreadScheduledExecutor(r -> {
final var thread = Executors.defaultThreadFactory().newThread(r);
thread.setName("EarlyDisplay");
thread.setDaemon(true);
return thread;
});
private int fbWidth;
private int fbHeight;
private int fbScale;
@@ -149,7 +154,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
}
this.maximized = parsed.has(maximizedopt) || FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_MAXIMIZED);
StartupNotificationManager.modLoaderConsumer().ifPresent(c->c.accept("Forge loading " + forgeVersion));
StartupNotificationManager.modLoaderConsumer().ifPresent(c->c.accept("Forge loading " + FMLLoader.versionInfo().forgeVersion()));
performanceInfo = new PerformanceInfo();
return start(mcVersion, forgeVersion);
}
@@ -238,7 +243,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
var date = Calendar.getInstance();
if (FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SQUIR) || (date.get(Calendar.MONTH) == Calendar.APRIL && date.get(Calendar.DAY_OF_MONTH) == 1))
this.elements.add(0, RenderElement.squir());
this.elements.addFirst(RenderElement.squir());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -287,12 +292,6 @@ public class DisplayWindow implements ImmediateWindowProvider {
* Start the window and Render Thread; we're ready to go.
*/
public Runnable start(@Nullable String mcVersion, final String forgeVersion) {
renderScheduler = Executors.newSingleThreadScheduledExecutor(r -> {
final var thread = Executors.defaultThreadFactory().newThread(r);
thread.setName("EarlyDisplay");
thread.setDaemon(true);
return thread;
});
initWindow(mcVersion);
this.initializationFuture = renderScheduler.schedule(() -> initRender(mcVersion, forgeVersion), 1, TimeUnit.MILLISECONDS);
return this::periodicTick;
@@ -304,7 +303,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
return this.glVersion;
}
private void crashElegantly(String errorDetails) {
private static void crashElegantly(String errorDetails) {
StringBuilder msgBuilder = new StringBuilder(2000);
msgBuilder.append("Failed to initialize graphics window with current settings.\n");
msgBuilder.append("\n\n");
@@ -512,7 +511,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
this.winY = y;
}
}
private void handleLastGLFWError(BiConsumer<Integer, String> handler) {
private static void handleLastGLFWError(BiConsumer<Integer, String> handler) {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
PointerBuffer pointerbuffer = memorystack.mallocPointer(1);
int error = glfwGetError(pointerbuffer);
@@ -640,7 +639,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
}
public void addMojangTexture(final int textureId) {
this.elements.add(0, RenderElement.mojang(textureId, framecount));
this.elements.addFirst(RenderElement.mojang(textureId, framecount));
}
public void close() {
@@ -13,10 +13,10 @@ 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;
private float memory;
private String text;
@@ -24,15 +24,14 @@ public class PerformanceInfo {
PerformanceInfo() {
showCPUUsage = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SHOW_CPU);
osBean = showCPUUsage ? ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class) : null;
memoryBean = ManagementFactory.getMemoryMXBean();
}
void update() {
final MemoryUsage heapusage = memoryBean.getHeapMemoryUsage();
final MemoryUsage heapusage = MEMORY_BEAN.getHeapMemoryUsage();
memory = (float) heapusage.getUsed() / heapusage.getMax();
if (!showCPUUsage) {
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB".formatted(heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20);
text = "Memory: %d/%dMB (%.1f%%)".formatted(heapusage.getUsed() >>> 20, heapusage.getMax() >>> 20, memory * 100f);
return;
}
@@ -44,7 +43,7 @@ public class PerformanceInfo {
cpuText = "CPU: %.1f%%".formatted(cpuLoad * 100f);
}
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s".formatted(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() {
@@ -22,8 +22,8 @@ public class RenderElement {
static int globalAlpha = 255;
private int retireCount;
@FunctionalInterface
interface Renderer {
void accept(SimpleBufferBuilder bb, DisplayContext context, int frame);
default Renderer then(Renderer r) {
@@ -38,6 +38,9 @@ public class RenderElement {
interface TextureRenderer {
void accept(SimpleBufferBuilder bb, DisplayContext context, int[] size, int frame);
}
/** @deprecated Use {@link Renderer} directly. This was always eagerly resolved, making it an unnecessary wrapper. */
@Deprecated(since = "1.21.5", forRemoval = true)
@FunctionalInterface
interface Initializer extends Supplier<Renderer> {}
@@ -56,11 +59,18 @@ public class RenderElement {
}
}
/** @deprecated Use {@link RenderElement#RenderElement(Renderer)} instead */
@Deprecated(since = "1.21.5", forRemoval = true)
public RenderElement(final Initializer rendererInitializer) {
this.bb = new SimpleBufferBuilder(1);
this.renderer = rendererInitializer.get();
}
public RenderElement(Renderer renderer) {
this.bb = new SimpleBufferBuilder(1);
this.renderer = renderer;
}
public boolean render(DisplayContext ctx, int count) {
this.renderer.accept(bb, ctx, count);
return this.retireCount == 0 || this.retireCount < count;
@@ -75,7 +85,7 @@ public class RenderElement {
List<SimpleFont.DisplayText> texts = new ArrayList<>();
for (int i = messages.size() - 1; i >= 0; i--) {
final StartupNotificationManager.AgeMessage pair = messages.get(i);
final float fade = clamp((4000.0f - (float) pair.age() - ( i - 4 ) * 1000.0f) / 5000.0f, 0.0f, 1.0f);
final float fade = Math.clamp((4000.0f - (float) pair.age() - ( i - 4 ) * 1000.0f) / 5000.0f, 0.0f, 1.0f);
if (fade <0.01f) continue;
Message msg = pair.message();
int colour = Math.min((int)(fade * 255f), globalAlpha) << 24 | 0xFFFFFF;
@@ -84,19 +94,9 @@ public class RenderElement {
font.generateVerticesForTexts(10, context.scaledHeight() - texts.size() * font.lineSpacing() + font.descent() - 10, bb, texts.toArray(SimpleFont.DisplayText[]::new));
}
public static RenderElement monag() {
return new RenderElement(RenderElement.initializeTexture("monagstudios.png", 45000, 4, (bb, ctx, sz, frame) -> {
var size = 256;
var x0 = (ctx.width() - 2 * size) / 2;
var y0 = 64;
QuadHelper.loadQuad(bb, x0, x0+size, y0, y0+size/2f, 0f, 1f, 0f, 0.5f, 0xFFFFFFFF);
QuadHelper.loadQuad(bb, x0+size, x0+2*size, y0, y0+size/2f, 0f, 1f, 0.5f, 1f, 0xFFFFFFFF);
}));
}
public static RenderElement mojang(final int textureId, final int frameStart) {
return new RenderElement(()->(bb, ctx, frame) -> {
return new RenderElement((bb, ctx, frame) -> {
var size = 256 * ctx.scale();
var x0 = (ctx.scaledWidth() - 2 * size) / 2;
var y0 = 64 * ctx.scale() + 32;
@@ -148,11 +148,11 @@ public class RenderElement {
}));
}
public static RenderElement progressBars(SimpleFont font) {
return new RenderElement(() -> (bb, ctx, frame) -> RenderElement.startupProgressBars(font, bb, ctx, frame));
return new RenderElement((bb, ctx, frame) -> RenderElement.startupProgressBars(font, bb, ctx, frame));
}
public static RenderElement performanceBar(SimpleFont font) {
return new RenderElement(() -> (bb, ctx, frame) -> RenderElement.memoryInfo(font, bb, ctx, frame));
return new RenderElement((bb, ctx, frame) -> RenderElement.memoryInfo(font, bb, ctx, frame));
}
public static void startupProgressBars(SimpleFont font, final SimpleBufferBuilder buffer, final DisplayContext context, final int frameNumber) {
@@ -187,10 +187,10 @@ public class RenderElement {
}
private static float[] indeterminateBar(int frame, boolean isActive) {
if (RenderElement.globalAlpha != 0xFF || !isActive) {
return new float[] {0f,1f};
return new float[] { 0f, 1f };
} else {
var progress = frame % 100;
return new float[]{clamp((progress - 2) / 100f, 0f, 1f), clamp((progress + 2) / 100f, 0f, 1f)};
int progress = frame % 100;
return new float[] { Math.clamp((progress - 2) / 100f, 0f, 1f), Math.clamp((progress + 2) / 100f, 0f, 1f) };
}
}
@@ -249,8 +249,8 @@ public class RenderElement {
};
}
private static Initializer initializeText(SimpleFont font, TextGenerator textGenerator) {
return () -> (bb, context, frame) -> renderText(font, textGenerator, bb, context);
private static Renderer initializeText(SimpleFont font, TextGenerator textGenerator) {
return (bb, context, frame) -> renderText(font, textGenerator, bb, context);
}
private static void renderText(final SimpleFont font, final TextGenerator textGenerator, final SimpleBufferBuilder bb, final DisplayContext context) {
@@ -264,14 +264,13 @@ public class RenderElement {
private static TextGenerator text(int x, int y, String text, int colour) {
return (bb, font, context) -> font.generateVerticesForTexts(x, y, bb, new SimpleFont.DisplayText(text, colour));
}
private static Initializer initializeTexture(final String textureFileName, int size, int textureNumber, TextureRenderer positionAndColour) {
return ()->{
int[] imgSize = STBHelper.loadTextureFromClasspath(textureFileName, size, GL_TEXTURE0 + textureNumber + INDEX_TEXTURE_OFFSET);
return (bb, ctx, frame) -> {
ctx.elementShader().updateTextureUniform(textureNumber + INDEX_TEXTURE_OFFSET);
ctx.elementShader().updateRenderTypeUniform(ElementShader.RenderType.TEXTURE);
renderTexture(bb, ctx, frame, imgSize, positionAndColour);
};
private static Renderer initializeTexture(final String textureFileName, int size, int textureNumber, TextureRenderer positionAndColour) {
int[] imgSize = STBHelper.loadTextureFromClasspath(textureFileName, size, GL_TEXTURE0 + textureNumber + INDEX_TEXTURE_OFFSET);
return (bb, ctx, frame) -> {
ctx.elementShader().updateTextureUniform(textureNumber + INDEX_TEXTURE_OFFSET);
ctx.elementShader().updateRenderTypeUniform(ElementShader.RenderType.TEXTURE);
renderTexture(bb, ctx, frame, imgSize, positionAndColour);
};
}
@@ -281,21 +280,13 @@ public class RenderElement {
bb.draw();
}
@Deprecated(since = "1.21.5", forRemoval = true)
public static float clamp(float num, float min, float max) {
if (num < min) {
return min;
} else {
return Math.min(num, max);
}
return Math.clamp(num, min, max);
}
public static int clamp(int num, int min, int max) {
if (num < min) {
return min;
} else {
return Math.min(num, max);
}
return Math.min(max, Math.max(num, min));
}
public static int hsvToRGB(float hue, float saturation, float value) {
@@ -22,7 +22,7 @@ public class SimpleFont {
private final int textureNumber;
private final int lineSpacing;
private final int descent;
private final int GLYPH_COUNT = 127-32;
private static final int GLYPH_COUNT = 127 - 32;
private final Glyph[] glyphs;
private record Glyph(char c, int charwidth, int[] pos, float[] uv) {
@@ -120,7 +120,7 @@ public class SimpleFont {
case '\n', '\t' -> 0;
case ' ' -> glyphs[0].charwidth();
default -> {
if (c - 32 < this.GLYPH_COUNT && c > 32) {
if (c - 32 < GLYPH_COUNT && c > 32) {
yield this.glyphs[c - 32].charwidth();
} else {
yield 0;
@@ -151,7 +151,7 @@ public class SimpleFont {
case '\t' -> new Pos(pos.x()+font.glyphs[0].charwidth() * 4, pos.y(), pos.minx());
case ' ' -> new Pos(pos.x()+font.glyphs[0].charwidth(), pos.y(), pos.minx());
default -> {
if (c-32 < font.GLYPH_COUNT && c > 32) {
if (c-32 < GLYPH_COUNT && c > 32) {
pos = font.glyphs[c - 32].loadQuad(pos, colour(), bb);
}
yield pos;
+21 -1
View File
@@ -5,6 +5,7 @@ plugins {
id 'maven-publish'
id 'net.minecraftforge.licenser'
id 'net.minecraftforge.gradleutils'
alias(libs.plugins.apt)
}
apply from: rootProject.file('build_shared.gradle')
@@ -36,6 +37,7 @@ dependencies {
implementation(libs.terminalconsoleappender)
implementation(libs.jimfs)
// Needed because we have a custom log4j plugin, and they removed package scanning and require a data file to be generated
implementation(libs.log4j.core)
annotationProcessor(libs.bundles.log4j)
@@ -85,7 +87,7 @@ publishing {
license PomUtils.Licenses.LGPLv2_1
}
}
repositories {
maven gradleutils.publishingForgeMaven
}
@@ -102,5 +104,23 @@ tasks.register('writeForgeVersionJson') {
}
tasks.named('generateResources').configure {
dependsOn('eclipseJdt')
dependsOn('eclipseJdtApt')
dependsOn('eclipseFactorypath')
dependsOn('writeForgeVersionJson')
}
eclipse {
classpath {
// We need to set the default output directory for the log4j annotation processor
// Ideally we'd just set the value, but the eclipse plugin deduplicates the output directories
// So we have to do a hacky whenMerged
//defaultOutputDir = file('bin/main')
file.whenMerged {
entries.each { entry ->
if (entry.kind == 'output' && entry.hasProperty('path'))
entry.path = 'bin/main'
}
}
}
}
@@ -50,7 +50,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
@@ -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,6 +36,9 @@ 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.toUnmodifiableMap(VanillaObjectHolderData::holderClass, Function.identity()));
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;
@@ -47,9 +51,26 @@ 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"))
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 static boolean hasHolder(List<AnnotationNode> lst) {
@@ -48,9 +48,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
@@ -59,15 +65,14 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
if ((classNode.access & Opcodes.ACC_ENUM) == 0)
return ComputeFlags.NO_REWRITE;
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);
if (!classNode.interfaces.contains(MARKER_IFACE.getInternalName())) {
return ComputeFlags.NO_REWRITE;
}
//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"))
@@ -7,7 +7,6 @@ package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.*;
import joptsimple.OptionSpecBuilder;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.Environment;
import org.jetbrains.annotations.NotNull;
@@ -19,7 +18,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class FMLServiceProvider implements ITransformationService {
@@ -40,6 +40,21 @@ public class RuntimeDistCleaner implements ILaunchPluginService {
return "runtimedistcleaner";
}
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
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;
}
@Override
public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) {
var changed = false;
@@ -198,14 +213,6 @@ public class RuntimeDistCleaner implements ILaunchPluginService {
};
}
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
return isEmpty ? NAY : YAY;
}
private static class LambdaGatherer extends MethodVisitor {
private static final Handle META_FACTORY = new Handle(Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory", "metafactory",
@@ -18,9 +18,7 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A wrapper for {@link HighlightConverter} that auto-disables ANSI when the terminal doesn't support it.
@@ -9,7 +9,6 @@ import cpw.mods.modlauncher.api.LamdbaExceptionUtils.Supplier_WithExceptions;
import net.minecraftforge.fml.loading.StringUtils;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.stream.Stream;
@@ -17,7 +17,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
@@ -46,7 +46,7 @@ record Scanner(ModFile fileToScan, ModFileScanData result) {
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
@@ -81,6 +81,10 @@ class ArgumentList {
.toArray(String[]::new);
}
public boolean has(String key) {
return this.values.containsKey(key);
}
public boolean hasValue(String key) {
return getOrDefault(key, null) != null;
}
@@ -22,6 +22,10 @@ abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
super(type, prefix);
}
protected CommonDevLaunchHandler(String name) {
super(name);
}
@Override public String getNaming() { return "mcp"; }
@Override public boolean isProduction() { return false; }
@@ -29,13 +33,35 @@ abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
protected String[] preLaunch(String[] arguments, ModuleLayer layer) {
super.preLaunch(arguments, layer);
var args = ArgumentList.from(arguments);
if (this.module == null) {
var entry = args.get("launchEntry");
if (entry == null)
throw new IllegalArgumentException("When using " + this.name() + " launch target you must specify a --launchEntry argument");
args.remove("launchEntry");
int idx = entry.indexOf('/');
if (idx == -1) {
this.module = "minecraft";
this.main = entry;
} else {
this.module = entry.substring(0, idx);
this.main = entry.substring(idx + 1);
}
if (args.has("launchData")) {
args.remove("launchData");
this.isData = true;
}
}
if (getDist().isDedicatedServer())
return arguments;
return args.getArguments();
if (isData())
return arguments;
var args = ArgumentList.from(arguments);
return args.getArguments();
String username = args.get("username");
if (username != null) { // Replace '#' placeholders with random numbers
@@ -29,17 +29,27 @@ import java.util.List;
public abstract class CommonLaunchHandler implements ILaunchHandlerService {
protected static final Logger LOGGER = LogUtils.getLogger();
protected final LaunchType type;
private final String prefix;
private final String name;
protected Dist dist = Dist.CLIENT;
protected boolean isData = false;
protected String module;
protected String main;
protected CommonLaunchHandler(LaunchType type, String prefix) {
this.type = type;
this.prefix = prefix;
this(prefix + type.name());
this.dist = type.dist();
this.isData = type.data();
this.module = type.module();
this.main = type.main();
}
@Override public String name() { return this.prefix + this.type.name(); }
public Dist getDist() { return this.type.dist(); }
public boolean isData() { return this.type.data(); }
protected CommonLaunchHandler(String name) {
this.name = name;
}
@Override public String name() { return this.name; }
public Dist getDist() { return this.dist; }
public boolean isData() { return this.isData; }
public boolean isProduction() { return false; }
public abstract String getNaming();
@@ -66,7 +76,7 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService {
}
protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) {
return () -> runTarget(this.type.module(), this.type.main(), arguments, gameLayer);
return () -> runTarget(this.module, this.main, arguments, gameLayer);
}
protected record LaunchType(String name, String module, String main, Dist dist, boolean data) {};
@@ -14,12 +14,14 @@ sealed abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
super(type, "forge_dev_");
}
private ForgeDevLaunchHandler(String name) {
super(name);
}
@Override
public List<Path> getMinecraftPaths() {
// The extra jar is on the classpath, so try and pull it out of the legacy classpath
var legacyCP = findClassPath();
var extra = findJarOnClasspath(legacyCP, "client-extra");
// The client extra jar is on the classpath we can try locating it using the .mcassetsroot which vanilla uses for loading data
var extra = getPathFromResource("assets/.mcassetsroot");
// Minecraft is an exploded directory, so find it.
var minecraft = getPathFromResource("net/minecraft/client/Minecraft.class");
var forge = getPathFromResource("net/minecraftforge/common/MinecraftForge.class");
@@ -62,4 +64,10 @@ sealed abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
super(SERVER_GAMETEST);
}
}
public static final class Custom extends ForgeDevLaunchHandler {
public Custom() {
super("forge_dev");
}
}
}
@@ -8,17 +8,18 @@ package net.minecraftforge.fml.loading.targets;
import net.minecraftforge.fml.loading.FMLLoader;
import java.nio.file.Path;
import java.util.List;
import java.util.function.BiPredicate;
import org.jetbrains.annotations.ApiStatus;
import cpw.mods.jarhandling.SecureJar;
@ApiStatus.Internal
sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
private ForgeUserdevLaunchHandler(LaunchType type) {
super(type, "forge_userdev_");
}
private ForgeUserdevLaunchHandler(String name) {
super(name);
}
@Override
public List<Path> getMinecraftPaths() {
var legacyCP = findClassPath();
@@ -26,7 +27,7 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
// Minecraft is extra jar {resources} + forge jar {patches}
// The MC extra and forge jars are on the classpath, so try and pull them out
var extra = findJarOnClasspath(legacyCP, "client-extra");
var extra = findJarOnClasspath(legacyCP, "client-extra"); // This should be "client-" + vers.mcAndMCPVersion() + "-extra" but FG6 qwerks
var forge = findJarOnClasspath(legacyCP, "forge-" + vers.mcAndForgeVersion());
// We need to filter the forge jar to just MC code
var minecraft = CommonDevLaunchHandler.getMinecraftOnly(extra, forge);
@@ -39,6 +40,12 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
}
}
public static final class ClientData extends ForgeUserdevLaunchHandler {
public ClientData() {
super(CLIENT_DATA);
}
}
public static final class Data extends ForgeUserdevLaunchHandler {
public Data() {
super(DATA);
@@ -56,4 +63,10 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
super(SERVER_GAMETEST);
}
}
public static final class Custom extends ForgeUserdevLaunchHandler {
public Custom() {
super("forge_userdev");
}
}
}
@@ -4,12 +4,16 @@ net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Server
# Mod Developers
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Client
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ClientData
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Custom
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Data
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Server
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ServerGameTest
#Working on Forge itself
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Client
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ClientData
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Custom
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Data
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Server
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ServerGameTest
+1 -1
View File
@@ -4,7 +4,7 @@
SPDX-License-Identifier: LGPL-2.1-only
-->
<Configuration status="warn" packages="net.minecrell.terminalconsole,net.minecrell.terminalconsole.util,com.mojang.util,cpw.mods.modlauncher.log,net.minecraftforge.fml.loading.log4j" shutdownHook="disable">
<Configuration status="warn" shutdownHook="disable">
<filters>
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="${sys:forge.logging.marker.networking:-DENY}" onMismatch="NEUTRAL"/>
+7 -7
View File
@@ -1,17 +1,17 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
org.gradle.jvmargs=-Xmx6G
org.gradle.daemon=false
org.gradle.parallel=true
JAVA_VERSION=21
MC_VERSION=1.21.4
MC_VERSION=1.21.5
MC_NEXT_VERSION=1.22
MCP_VERSION=20241203.143248
MCP_VERSION=20250325.155543
MAPPING_CHANNEL=official
MAPPING_VERSION=1.21.4
MAPPING_VERSION=1.21.5
// Set to true before the first build of a new MC version, so we don't do compatibility checks
# Set to true before the first build of a new MC version, so we don't do compatibility checks
CHECK_COMPATIBILITY=false
// Set to true to allow for fuzzy patching. Useful during updateing
UPDATING=false
# Set to true to allow for fuzzy patching. Useful during updateing
UPDATING=false
Binary file not shown.
+2 -1
View File
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+13 -9
View File
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
@@ -141,7 +145,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=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -149,7 +153,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=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -198,11 +202,11 @@ 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
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Vendored
+10 -10
View File
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
+35 -23
View File
@@ -2,7 +2,7 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.minecraftforge.gradle' version '[6.0.24,6.2)'
id 'net.minecraftforge.gradle' version '[6.0.36,6.2)'
}
version = mod_version
@@ -22,17 +22,13 @@ minecraft {
// official MCVersion Official field/method names from Mojang mapping files
// parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official
//
// You must be aware of the Mojang license when using the 'official' or 'parchment' mappings.
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
//
// Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge
// Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started
//
// Use non-default mappings at your own risk. They may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: mapping_channel, version: mapping_version
// Tell FG to not automtically create the reobf tasks, as we now use Official mappings at runtime, If you don't use them at dev time then you'll have to fix your reobf yourself.
// Forge 1.20.6 and newer use official mappings at runtime, so we shouldn't reobf from official to SRG
reobf = false
// When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game.
@@ -50,8 +46,7 @@ minecraft {
// By default, the folder name of a run configuration is the name of the Gradle project containing it.
// generateRunFolders = true
// This property enables access transformers for use in development.
// They will be applied to the Minecraft artifact.
// This property enables access transformers for use in development, applied to the Minecraft artifact.
// The access transformer file can be anywhere in the project.
// However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge.
// This default location is a best practice to automatically put the file in the right place in the final jar.
@@ -65,17 +60,15 @@ minecraft {
configureEach {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// Optional additional logging. The markers can be added/remove as needed, separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
// arg "-mixin.config=${mod_id}.mixins.json"
}
client {
@@ -110,7 +103,26 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
mavenCentral()
maven {
name = 'Forge'
url = 'https://maven.minecraftforge.net'
}
maven {
name = 'Minecraft libraries'
url = 'https://libraries.minecraft.net'
}
exclusiveContent {
forRepository {
maven {
name = 'Sponge'
url = 'https://repo.spongepowered.org/repository/maven-public'
}
}
filter {
includeGroupAndSubgroups('org.spongepowered')
}
}
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver
@@ -141,16 +153,13 @@ dependencies {
// For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
// Hack fix for now, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+
implementation('net.sf.jopt-simple:jopt-simple:5.0.4') { version { strictly '5.0.4' } }
}
// This block of code expands all declared replace properties in the specified resource targets.
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
tasks.named('processResources', ProcessResources).configure {
tasks.named('processResources', ProcessResources) {
var replaceProperties = [
minecraft_version: minecraft_version, minecraft_version_range: minecraft_version_range,
forge_version: forge_version, forge_version_range: forge_version_range,
@@ -166,7 +175,7 @@ tasks.named('processResources', ProcessResources).configure {
}
// Example for how to get properties into the manifest for reading at runtime.
tasks.named('jar', Jar).configure {
tasks.named('jar', Jar) {
manifest {
attributes([
'Specification-Title' : mod_id,
@@ -176,6 +185,7 @@ tasks.named('jar', Jar).configure {
'Implementation-Version' : project.jar.archiveVersion,
'Implementation-Vendor' : mod_authors
])
// attributes['MixinConfigs'] = "${mod_id}.mixins.json"
}
}
@@ -197,6 +207,9 @@ tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
// IntelliJ no longer downloads javadocs and sources by default, this tells Gradle to force IntelliJ to do it.
idea.module { downloadJavadoc = downloadSources = true }
eclipse {
// Run everytime eclipse builds the code
//autoBuildTasks genEclipseRuns
@@ -204,8 +217,7 @@ eclipse {
synchronizationTasks 'genEclipseRuns'
}
// Merge the resources and classes into the same directory.
// This is done because java expects modules to be in a single directory.
// Merge the resources and classes into the same directory, because Java expects modules to be in a single directory.
// And if we have it in multiple we have to do performance intensive hacks like having the UnionFileSystem
// This will eventually be migrated to ForgeGradle so modders don't need to manually do it. But that is later.
sourceSets.each {
+9 -2
View File
@@ -1,8 +1,15 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# Sets default memory used for Gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
org.gradle.jvmargs=-Xmx5G
org.gradle.daemon=false
# In the case that Gradle needs to fork to recompile, this will set the memory for that process.
systemProp.net.minecraftforge.gradle.repo.recompile.fork=true
systemProp.net.minecraftforge.gradle.repo.recompile.fork.args=-Xmx5G
# Opts-out of ForgeGradle automatically adding mavenCentral(), Forge's maven and MC libs maven to the repositories block
systemProp.net.minecraftforge.gradle.repo.attach=false
## Environment Properties
+2 -2
View File
@@ -9,5 +9,5 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0'
}
@@ -0,0 +1,12 @@
--- a/com/mojang/blaze3d/opengl/GlCommandEncoder.java
+++ b/com/mojang/blaze3d/opengl/GlCommandEncoder.java
@@ -109,6 +_,9 @@
GlStateManager._colorMask(true, true, true, true);
GlStateManager._clear(16384);
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, 0, 0);
+ // Forge: if using stencil, clear it as well (3553 = GlConst.GL_TEXTURE_2D)
+ if (p_394273_.isStencilEnabled())
+ GlStateManager._glFramebufferTexture2D(GlConst.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, GlConst.GL_TEXTURE_2D, 0, 0);
GlStateManager._glBindFramebuffer(36160, 0);
}
}
@@ -0,0 +1,34 @@
--- a/com/mojang/blaze3d/opengl/GlDebug.java
+++ b/com/mojang/blaze3d/opengl/GlDebug.java
@@ -23,6 +_,14 @@
@OnlyIn(Dist.CLIENT)
public class GlDebug {
+ /**
+ * TODO: [Forge][Rendering][VEN] Expose this in the configs
+ * <p>
+ * Will enable synchronous OpenGL debug logging, which means the message will be sent from the call that
+ * would have caused the error. Additionally, enables printing a stacktrace when and where this occurs.
+ */
+ private static final boolean PRINT_STACKTRACE_ON_ERROR = Boolean.getBoolean("forge.printGLStackOnError");
+
private static final Logger LOGGER = LogUtils.getLogger();
private static final int CIRCULAR_LOG_SIZE = 10;
private final Queue<GlDebug.LogEntry> MESSAGE_BUFFER = EvictingQueue.create(10);
@@ -105,6 +_,8 @@
}
LOGGER.info("OpenGL debug message: {}", gldebug$logentry);
+ // TODO: [VEN] Trim the stack trace
+ if (PRINT_STACKTRACE_ON_ERROR) LOGGER.info("Trace: ", new Throwable("GlDebug"));
}
public List<String> getLastOpenGlDebugMessages() {
@@ -121,6 +_,7 @@
@Nullable
public static GlDebug enableDebugCallback(int p_394351_, boolean p_393026_, Set<String> p_393339_) {
+ p_393026_ |= PRINT_STACKTRACE_ON_ERROR;
if (p_394351_ <= 0) {
return null;
} else {
@@ -0,0 +1,53 @@
--- a/com/mojang/blaze3d/opengl/GlDevice.java
+++ b/com/mojang/blaze3d/opengl/GlDevice.java
@@ -80,11 +_,25 @@
@Override
public GpuTexture createTexture(@Nullable Supplier<String> p_397830_, TextureFormat p_394839_, int p_394481_, int p_391831_, int p_395609_) {
- return this.createTexture(this.debugLabels.exists() && p_397830_ != null ? p_397830_.get() : null, p_394839_, p_394481_, p_391831_, p_395609_);
+ return this.createTexture(p_397830_, p_394839_, p_394481_, p_391831_, p_395609_, false);
+ }
+
+ /** @see GpuDevice#createTexture(Supplier, TextureFormat, int, int, int, boolean) */
+ @Override
+ public GpuTexture createTexture(@Nullable Supplier<String> p_397830_, TextureFormat p_394839_, int p_394481_, int p_391831_, int p_395609_, boolean stencil) {
+ return this.createTexture(this.debugLabels.exists() && p_397830_ != null ? p_397830_.get() : null, p_394839_, p_394481_, p_391831_, p_395609_, stencil);
}
@Override
public GpuTexture createTexture(@Nullable String p_394142_, TextureFormat p_394951_, int p_395535_, int p_393944_, int p_392329_) {
+ return this.createTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, false);
+ }
+
+ /** @see GpuDevice#createTexture(String, TextureFormat, int, int, int, boolean) */
+ @Override
+ public GpuTexture createTexture(@Nullable String p_394142_, TextureFormat p_394951_, int p_395535_, int p_393944_, int p_392329_, boolean stencil) {
+ // Forge: stencil rendering is only for depth
+ stencil &= p_394951_.hasDepthAspect();
if (p_392329_ < 1) {
throw new IllegalArgumentException("mipLevels must be at least 1");
} else {
@@ -106,11 +_,14 @@
GlStateManager._texImage2D(
3553,
j,
+ stencil ? org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8 :
GlConst.toGlInternalId(p_394951_),
p_395535_ >> j,
p_393944_ >> j,
0,
+ stencil ? org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL :
GlConst.toGlExternalId(p_394951_),
+ stencil ? org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV :
GlConst.toGlType(p_394951_),
null
);
@@ -122,7 +_,7 @@
} else if (k != 0) {
throw new IllegalStateException("OpenGL error " + k);
} else {
- GlTexture gltexture = new GlTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, i);
+ GlTexture gltexture = new GlTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, i, stencil);
this.debugLabels.applyLabel(gltexture);
return gltexture;
}
@@ -0,0 +1,32 @@
--- a/com/mojang/blaze3d/opengl/GlStateManager.java
+++ b/com/mojang/blaze3d/opengl/GlStateManager.java
@@ -90,6 +_,11 @@
}
}
+ public static boolean _isBlendEnabled() {
+ RenderSystem.assertOnRenderThread();
+ return BLEND.mode.enabled;
+ }
+
public static void _disableBlend() {
RenderSystem.assertOnRenderThread();
BLEND.mode.disable();
@@ -411,9 +_,17 @@
}
}
+ /* Stores the last values sent into glMultiTexCoord2f */
+ public static float lastBrightnessX = 0.0f;
+ public static float lastBrightnessY = 0.0f;
+
public static void _texParameter(int p_393876_, int p_397998_, int p_396741_) {
RenderSystem.assertOnRenderThread();
GL11.glTexParameteri(p_393876_, p_397998_, p_396741_);
+ if (p_393876_ == GL13.GL_TEXTURE1) {
+ lastBrightnessX = p_397998_;
+ lastBrightnessY = p_396741_;
+ }
}
public static int _getTexLevelParameter(int p_393352_, int p_397204_, int p_396319_) {
@@ -0,0 +1,32 @@
--- a/com/mojang/blaze3d/opengl/GlTexture.java
+++ b/com/mojang/blaze3d/opengl/GlTexture.java
@@ -18,8 +_,13 @@
protected boolean modesDirty = true;
protected GlTexture(String p_393950_, TextureFormat p_392837_, int p_394590_, int p_391379_, int p_391947_, int p_396659_) {
+ this(p_393950_, p_392837_, p_394590_, p_391379_, p_391947_, p_396659_, false);
+ }
+
+ protected GlTexture(String p_393950_, TextureFormat p_392837_, int p_394590_, int p_391379_, int p_391947_, int p_396659_, boolean stencil) {
super(p_393950_, p_392837_, p_394590_, p_391379_, p_391947_);
this.id = p_396659_;
+ this.stencilEnabled = stencil;
}
@Override
@@ -86,5 +_,15 @@
public void setTextureFilter(FilterMode p_394977_, FilterMode p_397175_, boolean p_393558_) {
super.setTextureFilter(p_394977_, p_397175_, p_393558_);
this.modesDirty = true;
+ }
+
+
+ /* FORGE START */
+
+ private final boolean stencilEnabled;
+
+ @Override
+ public boolean isStencilEnabled() {
+ return this.stencilEnabled;
}
}
@@ -1,28 +1,18 @@
--- a/com/mojang/blaze3d/pipeline/RenderTarget.java
+++ b/com/mojang/blaze3d/pipeline/RenderTarget.java
@@ -96,7 +_,10 @@
GlStateManager._texParameter(3553, 34892, 0);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
+ if (!stencilEnabled)
GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null);
+ else
+ GlStateManager._texImage2D(3553, 0, org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8, this.width, this.height, 0, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV, null);
}
this.setFilterMode(9728, true);
@@ -108,6 +_,7 @@
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
@@ -75,7 +_,7 @@
this.width = p_83951_;
this.height = p_83952_;
if (this.useDepth) {
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
+ if (stencilEnabled) GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
- this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", TextureFormat.DEPTH32, p_83951_, p_83952_, 1);
+ this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", TextureFormat.DEPTH32, p_83951_, p_83952_, 1, this.stencilEnabled);
this.depthTexture.setTextureFilter(FilterMode.NEAREST, false);
this.depthTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE);
}
this.checkStatus();
@@ -229,5 +_,26 @@
public int getDepthTextureId() {
return this.depthBufferId;
@@ -134,5 +_,26 @@
@Nullable
public GpuTexture getDepthTexture() {
return this.depthTexture;
+ }
+
+ private boolean stencilEnabled = false;
@@ -1,32 +0,0 @@
--- a/com/mojang/blaze3d/platform/GlStateManager.java
+++ b/com/mojang/blaze3d/platform/GlStateManager.java
@@ -94,6 +_,11 @@
}
}
+ public static boolean _isBlendEnabled() {
+ RenderSystem.assertOnRenderThread();
+ return BLEND.mode.enabled;
+ }
+
public static void _disableBlend() {
RenderSystem.assertOnRenderThread();
BLEND.mode.disable();
@@ -519,9 +_,17 @@
}
}
+ /* Stores the last values sent into glMultiTexCoord2f */
+ public static float lastBrightnessX = 0.0f;
+ public static float lastBrightnessY = 0.0f;
+
public static void _texParameter(int p_84161_, int p_84162_, float p_84163_) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glTexParameterf(p_84161_, p_84162_, p_84163_);
+ if (p_84161_ == GL13.GL_TEXTURE1) {
+ lastBrightnessX = p_84162_;
+ lastBrightnessY = p_84163_;
+ }
}
public static void _texParameter(int p_84332_, int p_84333_, int p_84334_) {
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/platform/Window.java
+++ b/com/mojang/blaze3d/platform/Window.java
@@ -89,7 +_,8 @@
@@ -88,7 +_,8 @@
GLFW.glfwWindowHint(139267, 2);
GLFW.glfwWindowHint(139272, 204801);
GLFW.glfwWindowHint(139270, 1);
@@ -10,15 +10,15 @@
if (monitor != null) {
VideoMode videomode = monitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
this.windowedX = this.x = monitor.getX() + videomode.getWidth() / 2 - this.width / 2;
@@ -101,6 +_,7 @@
@@ -100,6 +_,7 @@
this.windowedX = this.x = aint1[0];
this.windowedY = this.y = aint[0];
}
+ }
GLFW.glfwMakeContextCurrent(this.window);
GL.createCapabilities();
@@ -271,6 +_,9 @@
this.setMode();
this.refreshFramebufferSize();
@@ -266,6 +_,9 @@
GLFW.glfwGetFramebufferSize(this.window, aint, aint1);
this.framebufferWidth = aint[0] > 0 ? aint[0] : 1;
this.framebufferHeight = aint1[0] > 0 ? aint1[0] : 1;
@@ -0,0 +1,20 @@
--- a/com/mojang/blaze3d/systems/GpuDevice.java
+++ b/com/mojang/blaze3d/systems/GpuDevice.java
@@ -25,7 +_,17 @@
GpuTexture createTexture(@Nullable Supplier<String> p_394357_, TextureFormat p_395807_, int p_395623_, int p_395802_, int p_396157_);
+ /** Forge: same as {@link #createTexture(Supplier, TextureFormat, int, int, int)} but with stencil support */
+ default GpuTexture createTexture(@Nullable Supplier<String> p_394357_, TextureFormat p_395807_, int p_395623_, int p_395802_, int p_396157_, boolean stencil) {
+ return this.createTexture(p_394357_, p_395807_, p_395623_, p_395802_, p_396157_);
+ }
+
GpuTexture createTexture(@Nullable String p_391798_, TextureFormat p_393333_, int p_391800_, int p_395600_, int p_394065_);
+
+ /** Forge: same as {@link #createTexture(String, TextureFormat, int, int, int)} but with stencil support */
+ default GpuTexture createTexture(@Nullable String p_391798_, TextureFormat p_393333_, int p_391800_, int p_395600_, int p_394065_, boolean stencil) {
+ return this.createTexture(p_391798_, p_393333_, p_391800_, p_395600_, p_394065_);
+ }
GpuBuffer createBuffer(@Nullable Supplier<String> p_395215_, BufferType p_392847_, BufferUsage p_391478_, int p_397054_);
@@ -1,14 +0,0 @@
--- a/com/mojang/blaze3d/systems/RenderSystem.java
+++ b/com/mojang/blaze3d/systems/RenderSystem.java
@@ -196,6 +_,11 @@
GlStateManager._depthMask(p_69459_);
}
+ public static boolean isBlendEnabled() {
+ assertOnRenderThread();
+ return GlStateManager._isBlendEnabled();
+ }
+
public static void enableBlend() {
assertOnRenderThread();
GlStateManager._enableBlend();
@@ -0,0 +1,11 @@
--- a/com/mojang/blaze3d/textures/GpuTexture.java
+++ b/com/mojang/blaze3d/textures/GpuTexture.java
@@ -6,7 +_,7 @@
@OnlyIn(Dist.CLIENT)
@DontObfuscate
-public abstract class GpuTexture implements AutoCloseable {
+public abstract class GpuTexture implements AutoCloseable, net.minecraftforge.client.extensions.IForgeGpuTexture {
private final TextureFormat format;
private final int width;
private final int height;
@@ -1,11 +1,11 @@
--- a/com/mojang/blaze3d/vertex/PoseStack.java
+++ b/com/mojang/blaze3d/vertex/PoseStack.java
@@ -14,7 +_,7 @@
import org.joml.Vector3f;
@@ -15,7 +_,7 @@
import org.joml.Vector3fc;
@OnlyIn(Dist.CLIENT)
-public class PoseStack {
+public class PoseStack implements net.minecraftforge.client.extensions.IForgePoseStack {
private final Deque<PoseStack.Pose> poseStack = Util.make(Queues.newArrayDeque(), p_85848_ -> {
Matrix4f matrix4f = new Matrix4f();
Matrix3f matrix3f = new Matrix3f();
private final List<PoseStack.Pose> poses = new ArrayList<>(16);
private int lastIndex;
@@ -1,23 +1,23 @@
--- a/com/mojang/blaze3d/vertex/VertexFormat.java
+++ b/com/mojang/blaze3d/vertex/VertexFormat.java
@@ -14,7 +_,7 @@
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -20,7 +_,7 @@
@OnlyIn(Dist.CLIENT)
@DontObfuscate
-public class VertexFormat {
+public class VertexFormat implements net.minecraftforge.client.extensions.IForgeVertexFormat {
public static final int UNKNOWN_ELEMENT = -1;
private final List<VertexFormatElement> elements;
private final List<String> names;
@@ -23,6 +_,7 @@
private final int[] offsetsByElement = new int[32];
@@ -31,6 +_,7 @@
private GpuBuffer immediateDrawVertexBuffer;
@Nullable
private VertexBuffer immediateDrawVertexBuffer;
private GpuBuffer immediateDrawIndexBuffer;
+ private final com.google.common.collect.ImmutableMap<String, VertexFormatElement> elementMapping;
VertexFormat(List<VertexFormatElement> p_343616_, List<String> p_345241_, IntList p_345522_, int p_344162_) {
this.elements = p_343616_;
@@ -35,6 +_,11 @@
@@ -43,6 +_,11 @@
int j = vertexformatelement != null ? p_343616_.indexOf(vertexformatelement) : -1;
this.offsetsByElement[i] = j != -1 ? p_345522_.getInt(j) : -1;
}
@@ -29,13 +29,13 @@
}
public static VertexFormat.Builder builder() {
@@ -141,6 +_,9 @@
@@ -146,6 +_,9 @@
return vertexbuffer;
return this.immediateDrawIndexBuffer;
}
+
+ public ImmutableMap<String, VertexFormatElement> getElementMapping() { return elementMapping; }
+ public int getOffset(int index) { return offsetsByElement[index]; }
@OnlyIn(Dist.CLIENT)
public static class Builder {
@DontObfuscate
@@ -1,15 +1,15 @@
--- a/com/mojang/math/Transformation.java
+++ b/com/mojang/math/Transformation.java
@@ -13,7 +_,7 @@
@@ -14,7 +_,7 @@
import org.joml.Quaternionf;
import org.joml.Vector3f;
-public final class Transformation {
+public final class Transformation implements net.minecraftforge.common.extensions.IForgeTransformation {
private final Matrix4f matrix;
private final Matrix4fc matrix;
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create(
p_269604_ -> p_269604_.group(
@@ -169,5 +_,19 @@
@@ -174,5 +_,19 @@
vector3f1.lerp(p_175938_.getScale(), p_175939_);
quaternionf1.slerp(p_175938_.getRightRotation(), p_175939_);
return new Transformation(vector3f, quaternionf, vector3f1, quaternionf1);
@@ -34,4 +34,4 @@
+ this.stackTrace = t.getStackTrace();
}
public static void populateBlockDetails(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, @Nullable BlockState p_178954_) {
public static void populateBlockDetails(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, BlockState p_178954_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/SharedConstants.java
+++ b/net/minecraft/SharedConstants.java
@@ -170,6 +_,7 @@
@@ -171,6 +_,7 @@
}
static {
@@ -1,6 +1,6 @@
--- a/net/minecraft/advancements/Advancement.java
+++ b/net/minecraft/advancements/Advancement.java
@@ -214,7 +_,11 @@
@@ -226,7 +_,11 @@
}
public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, String p_138391_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/advancements/AdvancementRewards.java
+++ b/net/minecraft/advancements/AdvancementRewards.java
@@ -41,6 +_,7 @@
@@ -40,6 +_,7 @@
LootParams lootparams = new LootParams.Builder(p_9990_.serverLevel())
.withParameter(LootContextParams.THIS_ENTITY, p_9990_)
.withParameter(LootContextParams.ORIGIN, p_9990_.position())
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Camera.java
+++ b/net/minecraft/client/Camera.java
@@ -120,9 +_,13 @@
@@ -118,9 +_,13 @@
}
protected void setRotation(float p_90573_, float p_90574_) {
@@ -15,7 +15,7 @@
FORWARDS.rotate(this.rotation, this.forwards);
UP.rotate(this.rotation, this.up);
LEFT.rotate(this.rotation, this.left);
@@ -238,6 +_,13 @@
@@ -236,6 +_,13 @@
public float getPartialTickTime() {
return this.partialTickTime;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/KeyboardHandler.java
+++ b/net/minecraft/client/KeyboardHandler.java
@@ -424,12 +_,12 @@
@@ -431,12 +_,12 @@
if (screen != null) {
try {
if (p_90897_ != 1 && p_90897_ != 2) {
@@ -15,7 +15,7 @@
return;
}
}
@@ -505,6 +_,7 @@
@@ -495,6 +_,7 @@
}
}
}
@@ -23,7 +23,7 @@
}
}
@@ -514,10 +_,10 @@
@@ -504,10 +_,10 @@
if (screen != null && this.minecraft.getOverlay() == null) {
try {
if (Character.isBmpCodePoint(p_90891_)) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Minecraft.java
+++ b/net/minecraft/client/Minecraft.java
@@ -250,7 +_,7 @@
@@ -248,7 +_,7 @@
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
@@ -9,7 +9,7 @@
static Minecraft instance;
private static final Logger LOGGER = LogUtils.getLogger();
public static final boolean ON_OSX = Util.getPlatform() == Util.OS.OSX;
@@ -428,7 +_,6 @@
@@ -426,7 +_,6 @@
}
}, Util.nonCriticalIoPool());
LOGGER.info("Setting user: {}", this.user.getName());
@@ -17,7 +17,7 @@
this.demo = p_91084_.game.demo;
this.allowsMultiplayer = !p_91084_.game.disableMultiplayer;
this.allowsChat = !p_91084_.game.disableChat;
@@ -475,15 +_,15 @@
@@ -478,10 +_,9 @@
LOGGER.error("Couldn't set icon", (Throwable)ioexception);
}
@@ -26,16 +26,18 @@
- this.mouseHandler.setup(this.window.getWindow());
this.keyboardHandler = new KeyboardHandler(this);
- this.keyboardHandler.setup(this.window.getWindow());
RenderSystem.initRenderer(this.options.glDebugVerbosity, false);
RenderSystem.initRenderer(
this.window.getWindow(),
this.options.glDebugVerbosity,
@@ -492,6 +_,7 @@
LOGGER.info("Using optional rendering extensions: {}", String.join(", ", RenderSystem.getDevice().getEnabledExtensions()));
this.mainRenderTarget = new MainTarget(this.window.getWidth(), this.window.getHeight());
this.mainRenderTarget.setClearColor(0.0F, 0.0F, 0.0F, 0.0F);
this.mainRenderTarget.clear();
this.resourceManager = new ReloadableResourceManager(PackType.CLIENT_RESOURCES);
+ net.minecraftforge.client.loading.ClientModLoader.begin(this, this.resourcePackRepository, this.resourceManager);
this.resourcePackRepository.reload();
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
this.languageManager = new LanguageManager(this.options.languageCode, p_340763_ -> {
@@ -561,6 +_,7 @@
@@ -570,6 +_,7 @@
this.blockEntityRenderDispatcher = new BlockEntityRenderDispatcher(this.font, this.modelManager.entityModels(), this.blockRenderer, this.itemModelResolver, this.itemRenderer, this.entityRenderDispatcher);
this.resourceManager.registerReloadListener(this.blockEntityRenderDispatcher);
this.particleEngine = new ParticleEngine(this.level, this.textureManager);
@@ -43,7 +45,7 @@
this.resourceManager.registerReloadListener(this.particleEngine);
this.paintingTextures = new PaintingTextureManager(this.textureManager);
this.resourceManager.registerReloadListener(this.paintingTextures);
@@ -576,6 +_,9 @@
@@ -585,6 +_,9 @@
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
this.resourceManager.registerReloadListener(this.regionalCompliancies);
this.gui = new Gui(this);
@@ -51,17 +53,17 @@
+ this.mouseHandler.setup(this.window.getWindow());
+ this.keyboardHandler.setup(this.window.getWindow());
this.debugRenderer = new DebugRenderer(this);
RealmsClient realmsclient = RealmsClient.create(this);
RealmsClient realmsclient = RealmsClient.getOrCreate(this);
this.realmsDataFetcher = new RealmsDataFetcher(realmsclient);
@@ -599,6 +_,7 @@
this.options.fullscreen().set(this.window.isFullscreen());
@@ -618,6 +_,7 @@
}
}
+ net.minecraftforge.client.ForgeHooksClient.initClientHooks(this, this.resourceManager);
this.window.updateVsync(this.options.enableVsync().get());
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
this.window.setDefaultErrorCallback();
@@ -620,16 +_,17 @@
@@ -639,16 +_,17 @@
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, p_91084_.quickPlay);
this.setOverlay(
@@ -69,20 +71,20 @@
- this, reloadinstance, p_296164_ -> Util.ifElse(p_296164_, p_296162_ -> this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie), () -> {
+ net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(
+ () -> this, () -> reloadinstance, p_296164_ -> Util.ifElse(p_296164_, p_296162_ -> this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie), () -> {
if (SharedConstants.IS_RUNNING_IN_IDE) {
this.selfTest();
}
if (SharedConstants.IS_RUNNING_IN_IDE) {
this.selfTest();
}
this.reloadStateTracker.finishReload();
this.onResourceLoadFinished(minecraft$gameloadcookie);
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
}), false
this.reloadStateTracker.finishReload();
this.onResourceLoadFinished(minecraft$gameloadcookie);
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
}), false
- )
+ ).get()
);
this.quickPlayLog = QuickPlayLog.of(p_91084_.quickPlay.path());
this.framerateLimitTracker = new FramerateLimitTracker(this.options, this);
@@ -724,6 +_,7 @@
@@ -746,6 +_,7 @@
StringBuilder stringbuilder = new StringBuilder("Minecraft");
if (checkModStatus().shouldReportAsModified()) {
stringbuilder.append("*");
@@ -90,7 +92,7 @@
}
stringbuilder.append(" ");
@@ -747,6 +_,8 @@
@@ -769,6 +_,8 @@
}
private UserApiService createUserApiService(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
@@ -99,7 +101,7 @@
return p_193587_.user.user.getType() != User.Type.MSA
? UserApiService.OFFLINE
: p_193586_.createUserApiService(p_193587_.user.user.getAccessToken());
@@ -757,7 +_,7 @@
@@ -779,7 +_,7 @@
}
private void rollbackResourcePacks(Throwable p_91240_, @Nullable Minecraft.GameLoadCookie p_299515_) {
@@ -108,7 +110,7 @@
this.clearResourcePacksOnError(p_91240_, null, p_299515_);
} else {
Util.throwAsRuntime(p_91240_);
@@ -1043,12 +_,6 @@
@@ -1065,12 +_,6 @@
LOGGER.error("setScreen called from non-game thread");
}
@@ -121,7 +123,7 @@
if (p_91153_ == null && this.clientLevelTeardownInProgress) {
throw new IllegalStateException("Trying to return to in-game GUI during disconnection");
} else {
@@ -1062,6 +_,23 @@
@@ -1084,6 +_,23 @@
}
}
@@ -145,7 +147,15 @@
this.screen = p_91153_;
if (this.screen != null) {
this.screen.added();
@@ -1215,9 +_,11 @@
@@ -1168,6 +_,7 @@
FreeTypeUtil.destroy();
Util.shutdownExecutors();
RenderSystem.getDevice().close();
+ net.minecraftforge.fml.config.ConfigTracker.INSTANCE.forceUnload();
} catch (Throwable throwable) {
LOGGER.error("Shutdown failure!", throwable);
throw throwable;
@@ -1237,9 +_,11 @@
this.mouseHandler.handleAccumulatedMovement();
profilerfiller.pop();
if (!this.noRender) {
@@ -157,8 +167,8 @@
}
profilerfiller.push("blit");
@@ -1342,10 +_,12 @@
this.window.setGuiScale((double)i);
@@ -1363,10 +_,12 @@
this.window.setGuiScale(i);
if (this.screen != null) {
this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
+ net.minecraftforge.client.ForgeHooksClient.resizeGuiLayers(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
@@ -170,7 +180,7 @@
this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight());
this.mouseHandler.setIgnoreFirstMove();
}
@@ -1486,6 +_,7 @@
@@ -1504,6 +_,7 @@
}
public void stop() {
@@ -178,7 +188,7 @@
this.running = false;
}
@@ -1514,10 +_,18 @@
@@ -1532,10 +_,18 @@
if (p_91387_ && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
BlockPos blockpos = blockhitresult.getBlockPos();
@@ -200,7 +210,7 @@
this.player.swing(InteractionHand.MAIN_HAND);
}
}
@@ -1545,6 +_,8 @@
@@ -1563,6 +_,8 @@
return false;
} else {
boolean flag = false;
@@ -209,7 +219,7 @@
switch (this.hitResult.getType()) {
case ENTITY:
this.gameMode.attack(this.player, ((EntityHitResult)this.hitResult).getEntity());
@@ -1552,7 +_,7 @@
@@ -1570,7 +_,7 @@
case BLOCK:
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
BlockPos blockpos = blockhitresult.getBlockPos();
@@ -218,7 +228,7 @@
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
if (this.level.getBlockState(blockpos).isAir()) {
flag = true;
@@ -1565,8 +_,10 @@
@@ -1583,8 +_,10 @@
}
this.player.resetAttackStrengthTicker();
@@ -229,7 +239,7 @@
this.player.swing(InteractionHand.MAIN_HAND);
return flag;
}
@@ -1582,6 +_,12 @@
@@ -1600,6 +_,12 @@
}
for (InteractionHand interactionhand : InteractionHand.values()) {
@@ -242,7 +252,7 @@
ItemStack itemstack = this.player.getItemInHand(interactionhand);
if (!itemstack.isItemEnabled(this.level.enabledFeatures())) {
return;
@@ -1602,7 +_,7 @@
@@ -1620,7 +_,7 @@
}
if (interactionresult instanceof InteractionResult.Success interactionresult$success2) {
@@ -251,16 +261,16 @@
this.player.swing(interactionhand);
}
@@ -1614,7 +_,7 @@
@@ -1632,7 +_,7 @@
int i = itemstack.getCount();
InteractionResult interactionresult1 = this.gameMode.useItemOn(this.player, interactionhand, blockhitresult);
if (interactionresult1 instanceof InteractionResult.Success interactionresult$success) {
- if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT) {
+ if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
this.player.swing(interactionhand);
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.gameMode.hasInfiniteItems())) {
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.player.hasInfiniteMaterials())) {
this.gameRenderer.itemInHandRenderer.itemUsed(interactionhand);
@@ -1630,6 +_,9 @@
@@ -1648,6 +_,9 @@
}
}
@@ -270,7 +280,7 @@
if (!itemstack.isEmpty()
&& this.gameMode.useItem(this.player, interactionhand) instanceof InteractionResult.Success interactionresult$success1) {
if (interactionresult$success1.swingSource() == InteractionResult.SwingSource.CLIENT) {
@@ -1659,6 +_,8 @@
@@ -1677,6 +_,8 @@
}
ProfilerFiller profilerfiller = Profiler.get();
@@ -279,7 +289,7 @@
profilerfiller.push("gui");
this.chatListener.tick();
this.gui.tick(this.pause);
@@ -1748,6 +_,7 @@
@@ -1766,6 +_,7 @@
this.tutorial.tick();
@@ -287,7 +297,7 @@
try {
this.level.tick(() -> true);
} catch (Throwable throwable1) {
@@ -1761,6 +_,7 @@
@@ -1779,6 +_,7 @@
throw new ReportedException(crashreport1);
}
@@ -295,7 +305,7 @@
}
profilerfiller.popPush("animateTick");
@@ -1785,6 +_,7 @@
@@ -1803,6 +_,7 @@
profilerfiller.popPush("keyboard");
this.keyboardHandler.tick();
profilerfiller.pop();
@@ -303,7 +313,7 @@
}
private boolean isLevelRunningNormally() {
@@ -1986,6 +_,7 @@
@@ -2003,6 +_,7 @@
}
public void setLevel(ClientLevel p_91157_, ReceivingLevelScreen.Reason p_335893_) {
@@ -311,7 +321,7 @@
this.updateScreenAndTick(new ReceivingLevelScreen(() -> false, p_335893_));
this.level = p_91157_;
this.updateLevelInEngines(p_91157_);
@@ -2023,6 +_,7 @@
@@ -2040,6 +_,7 @@
IntegratedServer integratedserver = this.singleplayerServer;
this.singleplayerServer = null;
this.gameRenderer.resetData();
@@ -319,7 +329,7 @@
this.gameMode = null;
this.narrator.clear();
this.clientLevelTeardownInProgress = true;
@@ -2030,6 +_,7 @@
@@ -2047,6 +_,7 @@
try {
this.updateScreenAndTick(p_335030_);
if (this.level != null) {
@@ -327,7 +337,7 @@
if (integratedserver != null) {
ProfilerFiller profilerfiller = Profiler.get();
profilerfiller.push("waitForServer");
@@ -2043,6 +_,7 @@
@@ -2060,6 +_,7 @@
this.gui.onDisconnected();
this.isLocalServer = false;
@@ -335,11 +345,11 @@
}
this.level = null;
@@ -2190,6 +_,7 @@
@@ -2207,6 +_,7 @@
private void pickBlock() {
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onClickInput(2, this.options.keyPickItem, InteractionHand.MAIN_HAND).isCanceled()) return;
boolean flag = Screen.hasControlDown();
HitResult hitresult = this.hitResult;
Objects.requireNonNull(this.hitResult);
switch (this.hitResult) {
case BlockHitResult blockhitresult:
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/MouseHandler.java
+++ b/net/minecraft/client/MouseHandler.java
@@ -85,6 +_,7 @@
@@ -90,6 +_,7 @@
this.activeButton = -1;
}
@@ -8,7 +8,7 @@
if (this.minecraft.getOverlay() == null) {
if (this.minecraft.screen == null) {
if (!this.mouseGrabbed && flag) {
@@ -98,7 +_,7 @@
@@ -103,7 +_,7 @@
screen.afterMouseAction();
try {
@@ -17,7 +17,7 @@
return;
}
} catch (Throwable throwable1) {
@@ -112,7 +_,7 @@
@@ -116,7 +_,7 @@
}
} else {
try {
@@ -26,18 +26,18 @@
return;
}
} catch (Throwable throwable) {
@@ -147,6 +_,7 @@
@@ -150,6 +_,7 @@
}
}
}
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(p_91532_, p_91533_, p_91534_);
}
private void onScroll(long p_91527_, double p_91528_, double p_91529_) {
@@ -160,7 +_,9 @@
public void fillMousePositionDetails(CrashReportCategory p_398230_, Window p_398216_) {
@@ -189,7 +_,9 @@
if (this.minecraft.screen != null) {
double d3 = this.xpos * (double)this.minecraft.getWindow().getGuiScaledWidth() / (double)this.minecraft.getWindow().getScreenWidth();
double d4 = this.ypos * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
double d3 = this.getScaledXPos(this.minecraft.getWindow());
double d4 = this.getScaledYPos(this.minecraft.getWindow());
- this.minecraft.screen.mouseScrolled(d3, d4, d1, d2);
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPre(this.minecraft.screen, d3, d4, d1, d2)) return;
+ if (this.minecraft.screen.mouseScrolled(d3, d4, d1, d2)) return;
@@ -45,7 +45,7 @@
this.minecraft.screen.afterMouseAction();
} else if (this.minecraft.player != null) {
Vector2i vector2i = this.scrollWheelHandler.onMouseScroll(d1, d2);
@@ -169,6 +_,7 @@
@@ -198,6 +_,7 @@
}
int i = vector2i.y == 0 ? -vector2i.x : vector2i.y;
@@ -53,8 +53,8 @@
if (this.minecraft.player.isSpectator()) {
if (this.minecraft.gui.getSpectatorGui().isMenuActive()) {
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-i);
@@ -274,7 +_,7 @@
double d5 = this.accumulatedDY * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
@@ -303,7 +_,7 @@
double d5 = getScaledYPos(window, this.accumulatedDY);
try {
- screen.mouseDragged(d2, d3, this.activeButton, d4, d5);
@@ -62,7 +62,7 @@
} catch (Throwable throwable) {
CrashReport crashreport1 = CrashReport.forThrowable(throwable, "mouseDragged event handler");
screen.fillCrashDetails(crashreport1);
@@ -349,6 +_,14 @@
@@ -393,6 +_,14 @@
public double ypos() {
return this.ypos;
@@ -1,16 +1,24 @@
--- a/net/minecraft/client/Options.java
+++ b/net/minecraft/client/Options.java
@@ -698,7 +_,8 @@
@@ -668,7 +_,8 @@
},
new OptionInstance.LazyEnum<>(
() -> Stream.concat(Stream.of(""), Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().stream()).toList(),
- p_232011_ -> Minecraft.getInstance().isRunning() && p_232011_ != "" && !Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().contains(p_232011_)
+ // FORGE: fix incorrect string comparison - PR #8767
+ p_232011_ -> Minecraft.getInstance().isRunning() && (p_232011_ == null || !p_232011_.isEmpty()) && !Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().contains(p_232011_)
? Optional.empty()
: Optional.of(p_232011_),
? Optional.empty()
: Optional.of(p_232011_),
Codec.STRING
@@ -1079,6 +_,7 @@
@@ -683,6 +_,7 @@
public boolean onboardAccessibility = true;
public boolean syncWrites;
public boolean startedCleanly = true;
+ private final Map<String, String> unknownKeys = new java.util.HashMap<>();
public OptionInstance<Boolean> darkMojangStudiosBackground() {
return this.darkMojangStudiosBackground;
@@ -1050,6 +_,7 @@
}
public Options(Minecraft p_92138_, File p_92139_) {
@@ -18,15 +26,16 @@
this.minecraft = p_92138_;
this.optionsFile = new File(p_92139_, "options.txt");
boolean flag = Runtime.getRuntime().maxMemory() >= 1000000000L;
@@ -1210,12 +_,22 @@
p_168428_.process("telemetryOptInExtra", this.telemetryOptInExtra);
@@ -1181,15 +_,28 @@
this.onboardAccessibility = p_168428_.process("onboardAccessibility", this.onboardAccessibility);
p_168428_.process("menuBackgroundBlurriness", this.menuBackgroundBlurriness);
+ processOptionsForge(p_168428_);
this.startedCleanly = p_168428_.process("startedCleanly", this.startedCleanly);
+ processOptionsKeysOnly(p_168428_);
+ processOptionsEnd(p_168428_);
+ }
+ // FORGE: split off to allow reloading options after mod loading is done
+ private void processOptionsForge(Options.FieldAccess p_168428_) {
+ // FORGE: split off to allow reloading keys after mod loading is done
+ private void processOptionsKeysOnly(Options.FieldAccess p_168428_) {
for (KeyMapping keymapping : this.keyMappings) {
- String s = keymapping.saveString();
+ String s = keymapping.saveString() + (keymapping.getKeyModifier() != net.minecraftforge.client.settings.KeyModifier.NONE ? ":" + keymapping.getKeyModifier() : "");
@@ -41,8 +50,13 @@
+ }
}
}
+ }
@@ -1233,6 +_,10 @@
+ private void processOptionsEnd(Options.FieldAccess p_168428_) {
for (SoundSource soundsource : SoundSource.values()) {
p_168428_.process("soundCategory_" + soundsource.getName(), this.soundSourceVolumes.get(soundsource));
}
@@ -1204,6 +_,10 @@
}
public void load() {
@@ -53,17 +67,60 @@
try {
if (!this.optionsFile.exists()) {
return;
@@ -1260,7 +_,8 @@
}
@@ -1228,7 +_,8 @@
this.graphicsMode.set(isTrue(optional.get()) ? GraphicsStatus.FANCY : GraphicsStatus.FAST);
}
- this.processOptions(
+ java.util.function.Consumer<FieldAccess> processor = limited ? this::processOptionsForge : this::processOptions;
+ java.util.function.Consumer<FieldAccess> processor = limited ? this::processOptionsKeysOnly : this::processOptions;
+ processor.accept(
new Options.FieldAccess() {
@Nullable
private String getValueOrNull(String p_168459_) {
@@ -1451,6 +_,7 @@
private String getValue(String p_394210_) {
@@ -1310,6 +_,17 @@
);
compoundtag1.getString("fullscreenResolution").ifPresent(p_389133_ -> this.fullscreenVideoModeString = p_389133_);
KeyMapping.resetMapping();
+
+ if (limited) {
+ this.unknownKeys.clear();
+ } else {
+ var knownKeys = Arrays.stream(this.keyMappings).map(k -> "key_" + k.getName()).collect(Collectors.toSet());
+ for (var entry : compoundtag1.entrySet()) {
+ if (entry.getKey().startsWith("key_") && entry.getValue().asString().isPresent() && !knownKeys.contains(entry.getKey()))
+ this.unknownKeys.put(entry.getKey(), entry.getValue().asString().get());
+ }
+ }
+
} catch (Exception exception) {
LOGGER.error("Failed to load options", (Throwable)exception);
}
@@ -1337,9 +_,11 @@
public void save() {
try (final PrintWriter printwriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.optionsFile), StandardCharsets.UTF_8))) {
printwriter.println("version:" + SharedConstants.getCurrentVersion().getDataVersion().getVersion());
+ var seen = new java.util.HashSet<String>();
this.processOptions(
new Options.FieldAccess() {
public void writePrefix(String p_168491_) {
+ seen.add(p_168491_);
printwriter.print(p_168491_);
printwriter.print(':');
}
@@ -1395,6 +_,12 @@
if (s != null) {
printwriter.println("fullscreenResolution:" + s);
}
+ // Forge add any unknown keys so that Mods can add keybindings between vanilla loading/saving its config.
+ for (var entry : this.unknownKeys.entrySet()) {
+ if (!seen.contains(entry.getKey()))
+ printwriter.println(entry.getKey() + ":" + entry.getValue());
+ }
+
} catch (Exception exception) {
LOGGER.error("Failed to save options", (Throwable)exception);
}
@@ -1433,6 +_,7 @@
}
public void broadcastOptions() {
@@ -71,7 +128,7 @@
if (this.minecraft.player != null) {
this.minecraft.player.connection.broadcastClientInformation(this.buildPlayerInformation());
}
@@ -1564,6 +_,23 @@
@@ -1546,6 +_,23 @@
public static Component genericValueLabel(Component p_231901_, int p_231902_) {
return genericValueLabel(p_231901_, Component.literal(Integer.toString(p_231902_)));
@@ -1,30 +1,32 @@
--- a/net/minecraft/client/Screenshot.java
+++ b/net/minecraft/client/Screenshot.java
@@ -54,14 +_,24 @@
file2 = new File(file1, p_92307_);
}
@@ -43,6 +_,13 @@
file2 = new File(file1, p_92297_);
}
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenshot(nativeimage, file2);
+ if (event.isCanceled()) {
+ p_92311_.accept(event.getCancelMessage());
+ return;
+ }
+ final File target = event.getScreenshotFile();
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenshot(p_389141_, file2);
+ if (event.isCanceled()) {
+ p_92301_.accept(event.getCancelMessage());
+ return;
+ }
+ final File target = event.getScreenshotFile();
+
Util.ioPool()
.execute(
() -> {
try {
- nativeimage.writeToFile(file2);
- Component component = Component.literal(file2.getName())
+ nativeimage.writeToFile(target);
+ Component component = Component.literal(target.getName())
.withStyle(ChatFormatting.UNDERLINE)
- .withStyle(p_168608_ -> p_168608_.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, file2.getAbsolutePath())));
+ .withStyle(p_168608_ -> p_168608_.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, target.getAbsolutePath())));
+ if (event.getResultMessage() != null)
+ p_92311_.accept(event.getResultMessage());
+ else
p_92311_.accept(Component.translatable("screenshot.success", component));
} catch (Exception exception) {
LOGGER.warn("Couldn't save screenshot", (Throwable)exception);
Util.ioPool()
.execute(
() -> {
@@ -50,10 +_,13 @@
NativeImage $$4x = p_389141_;
try {
- p_389141_.writeToFile(file2);
- Component component = Component.literal(file2.getName())
+ p_389141_.writeToFile(target);
+ Component component = Component.literal(target.getName())
.withStyle(ChatFormatting.UNDERLINE)
.withStyle(p_389149_ -> p_389149_.withClickEvent(new ClickEvent.OpenFile(file2.getAbsoluteFile())));
+ if (event.getResultMessage() != null)
+ p_92301_.accept(event.getResultMessage());
+ else
p_92301_.accept(Component.translatable("screenshot.success", component));
} catch (Throwable throwable1) {
if (p_389141_ != null) {
@@ -10,7 +10,7 @@
private final Map<Block, Set<Property<?>>> coloringStates = Maps.newHashMap();
public static BlockColors createDefault() {
@@ -90,11 +_,12 @@
@@ -95,11 +_,12 @@
}, Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
blockcolors.addColoringState(StemBlock.AGE, Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
blockcolors.register((p_92596_, p_92597_, p_92598_, p_92599_) -> p_92597_ != null && p_92598_ != null ? -14647248 : -9321636, Blocks.LILY_PAD);
@@ -24,7 +24,7 @@
if (blockcolor != null) {
return blockcolor.getColor(p_92583_, null, null, 0);
} else {
@@ -104,13 +_,15 @@
@@ -109,13 +_,15 @@
}
public int getColor(BlockState p_92578_, @Nullable BlockAndTintGetter p_92579_, @Nullable BlockPos p_92580_, int p_92581_) {
@@ -15,7 +15,7 @@
boolean flag1 = flag || optionset.has(optionspec1);
Bootstrap.bootStrap();
ClientBootstrap.bootstrap();
+ if (!loader.run(optionset, path, input, flag, flag1, flag, flag, false))
+ if (!loader.run(optionset, path, input, flag, flag1, flag, flag, true))
+ return;
DataGenerator datagenerator = new DataGenerator(path, SharedConstants.getCurrentVersion(), true);
addClientProviders(datagenerator, flag1);
@@ -0,0 +1,12 @@
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
@@ -852,6 +_,9 @@
this.declareCustomModelItem(Items.COD);
this.declareCustomModelItem(Items.FEATHER);
this.declareCustomModelItem(Items.LEAD);
+ // moved from validate to here, because it's just vanilla default blocks
+ if (this.itemModelOutput instanceof ModelProvider.ItemInfoCollector collector)
+ collector.generateDefaultBlockModels();
}
@OnlyIn(Dist.CLIENT)
@@ -0,0 +1,111 @@
--- a/net/minecraft/client/data/models/ModelProvider.java
+++ b/net/minecraft/client/data/models/ModelProvider.java
@@ -45,11 +_,11 @@
@Override
public CompletableFuture<?> run(CachedOutput p_376268_) {
- ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector();
- ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector();
+ ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector(this::getKnownItems);
+ ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector(this::getKnownBlocks);
ModelProvider.SimpleModelCollector modelprovider$simplemodelcollector = new ModelProvider.SimpleModelCollector();
- new BlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
- new ItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
+ getBlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
+ getItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
modelprovider$blockstategeneratorcollector.validate();
modelprovider$iteminfocollector.finalizeAndValidate();
return CompletableFuture.allOf(
@@ -59,6 +_,22 @@
);
}
+ protected Stream<Block> getKnownBlocks() {
+ return BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace()));
+ }
+
+ protected Stream<Item> getKnownItems() {
+ return BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace()));
+ }
+
+ protected BlockModelGenerators getBlockModelGenerators(BlockStateGeneratorCollector blocks, ItemInfoCollector items, SimpleModelCollector models) {
+ return new BlockModelGenerators(blocks, items, models);
+ }
+
+ protected ItemModelGenerators getItemModelGenerators(ItemInfoCollector items, SimpleModelCollector models) {
+ return new ItemModelGenerators(items, models);
+ }
+
@Override
public final String getName() {
return "Model Definitions";
@@ -67,6 +_,15 @@
@OnlyIn(Dist.CLIENT)
public static class BlockStateGeneratorCollector implements Consumer<BlockModelDefinitionGenerator> {
private final Map<Block, BlockModelDefinitionGenerator> generators = new HashMap<>();
+ private final Supplier<Stream<Block>> known;
+
+ public BlockStateGeneratorCollector() {
+ this(() -> BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace())));
+ }
+
+ public BlockStateGeneratorCollector(Supplier<Stream<Block>> known) {
+ this.known = known;
+ }
public void accept(BlockModelDefinitionGenerator p_393399_) {
Block block = p_393399_.block();
@@ -77,7 +_,7 @@
}
public void validate() {
- Stream<Holder.Reference<Block>> stream = BuiltInRegistries.BLOCK.listElements().filter(p_376480_ -> true);
+ Stream<Holder.Reference<Block>> stream = known.get().map(Block::builtInRegistryHolder);
List<ResourceLocation> list = stream.filter(p_378423_ -> !this.generators.containsKey(p_378423_.value()))
.map(p_378200_ -> p_378200_.key().location())
.toList();
@@ -97,6 +_,15 @@
public static class ItemInfoCollector implements ItemModelOutput {
private final Map<Item, ClientItem> itemInfos = new HashMap<>();
private final Map<Item, Item> copies = new HashMap<>();
+ private final Supplier<Stream<Item>> known;
+
+ public ItemInfoCollector() {
+ this(() -> BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace())));
+ }
+
+ public ItemInfoCollector(Supplier<Stream<Item>> known) {
+ this.known = known;
+ }
@Override
public void accept(Item p_376450_, ItemModel.Unbaked p_378513_) {
@@ -115,7 +_,7 @@
this.copies.put(p_376965_, p_377438_);
}
- public void finalizeAndValidate() {
+ public void generateDefaultBlockModels() {
BuiltInRegistries.ITEM.forEach(p_378629_ -> {
if (!this.copies.containsKey(p_378629_)) {
if (p_378629_ instanceof BlockItem blockitem && !this.itemInfos.containsKey(blockitem)) {
@@ -124,6 +_,8 @@
}
}
});
+ }
+ public void finalizeAndValidate() {
this.copies.forEach((p_376289_, p_375718_) -> {
ClientItem clientitem = this.itemInfos.get(p_375718_);
if (clientitem == null) {
@@ -132,8 +_,8 @@
this.register(p_376289_, clientitem);
}
});
- List<ResourceLocation> list = BuiltInRegistries.ITEM
- .listElements()
+ List<ResourceLocation> list = known.get()
+ .map(item -> item.builtInRegistryHolder())
.filter(p_377225_ -> !this.itemInfos.containsKey(p_377225_.value()))
.map(p_378591_ -> p_378591_.key().location())
.toList();
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/Gui.java
+++ b/net/minecraft/client/gui/Gui.java
@@ -147,7 +_,7 @@
@@ -148,7 +_,7 @@
public float vignetteBrightness = 1.0F;
private int toolHighlightTimer;
private ItemStack lastToolHighlight = ItemStack.EMPTY;
@@ -9,16 +9,50 @@
private final SubtitleOverlay subtitleOverlay;
private final SpectatorGui spectatorGui;
private final PlayerTabOverlay tabList;
@@ -345,7 +_,7 @@
@@ -168,7 +_,7 @@
private int lastBubblePopSoundPlayed;
private float autosaveIndicatorValue;
private float lastAutosaveIndicatorValue;
- private final LayeredDraw layers = new LayeredDraw();
+ private final LayeredDraw layers = new net.minecraftforge.client.gui.overlay.ForgeLayeredDraw(net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.VANILLA_ROOT, net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.COMBINE_LIST);
private float scopeScale;
public Gui(Minecraft p_330021_) {
@@ -180,14 +_,14 @@
this.bossOverlay = new BossHealthOverlay(p_330021_);
this.subtitleOverlay = new SubtitleOverlay(p_330021_);
this.resetTitleTimes();
- LayeredDraw layereddraw = new LayeredDraw()
+ LayeredDraw layereddraw = new net.minecraftforge.client.gui.overlay.ForgeLayeredDraw(net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.PRE_SLEEP_STACK, net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.PRE_LIST)
.add(this::renderCameraOverlays)
.add(this::renderCrosshair)
.add(this::renderHotbarAndDecorations)
.add(this::renderExperienceLevel)
.add(this::renderEffects)
.add((p_325313_, p_342678_) -> this.bossOverlay.render(p_325313_));
- LayeredDraw layereddraw1 = new LayeredDraw()
+ LayeredDraw layereddraw1 = new net.minecraftforge.client.gui.overlay.ForgeLayeredDraw(net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.POST_SLEEP_STACK,net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.POST_LIST)
.add(this::renderDemoOverlay)
.add((p_325315_, p_344521_) -> {
if (this.debugOverlay.showDebugScreen()) {
@@ -204,6 +_,7 @@
.add(layereddraw, () -> !p_330021_.options.hideGui)
.add(this::renderSleepOverlay)
.add(layereddraw1, () -> !p_330021_.options.hideGui);
+ ((net.minecraftforge.client.gui.overlay.ForgeLayeredDraw) layers).resolveLayers();
}
public void resetTitleTimes() {
@@ -347,7 +_,7 @@
Window window = this.minecraft.getWindow();
int i = Mth.floor(this.minecraft.mouseHandler.xpos() * (double)window.getGuiScaledWidth() / (double)window.getScreenWidth());
int j = Mth.floor(this.minecraft.mouseHandler.ypos() * (double)window.getGuiScaledHeight() / (double)window.getScreenHeight());
int i = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
int j = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
- this.chat.render(p_329202_, this.tickCount, i, j, false);
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(p_329202_, this.chat, window, i, j, this.tickCount);
}
}
@@ -443,6 +_,8 @@
@@ -445,6 +_,8 @@
for (MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
Holder<MobEffect> holder = mobeffectinstance.getEffect();
@@ -27,7 +61,7 @@
if (mobeffectinstance.showIcon()) {
int k = p_282812_.guiWidth();
int l = 1;
@@ -473,6 +_,7 @@
@@ -475,6 +_,7 @@
}
}
@@ -35,7 +69,7 @@
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.get(holder);
int l1 = k;
int k1 = l;
@@ -623,6 +_,10 @@
@@ -625,6 +_,10 @@
}
private void renderSelectedItemName(GuiGraphics p_283501_) {
@@ -46,7 +80,7 @@
Profiler.get().push("selectedItemName");
if (this.toolHighlightTimer > 0 && !this.lastToolHighlight.isEmpty()) {
MutableComponent mutablecomponent = Component.empty().append(this.lastToolHighlight.getHoverName()).withStyle(this.lastToolHighlight.getRarity().color());
@@ -630,9 +_,13 @@
@@ -632,9 +_,13 @@
mutablecomponent.withStyle(ChatFormatting.ITALIC);
}
@@ -62,7 +96,7 @@
if (!this.minecraft.gameMode.canHurtPlayer()) {
k += 14;
}
@@ -643,7 +_,7 @@
@@ -645,7 +_,7 @@
}
if (l > 0) {
@@ -71,8 +105,8 @@
}
}
@@ -1152,7 +_,7 @@
ItemStack itemstack = this.minecraft.player.getInventory().getSelected();
@@ -1154,7 +_,7 @@
ItemStack itemstack = this.minecraft.player.getInventory().getSelectedItem();
if (itemstack.isEmpty()) {
this.toolHighlightTimer = 0;
- } else if (this.lastToolHighlight.isEmpty() || !itemstack.is(this.lastToolHighlight.getItem()) || !itemstack.getHoverName().equals(this.lastToolHighlight.getHoverName())) {
@@ -31,9 +31,9 @@
+ // Forge: Add float variant for x,y coordinates
+ public int drawString(Font p_282636_, FormattedCharSequence p_281596_, float p_281586_, float p_282816_, int p_281743_, boolean p_282394_) {
return p_282636_.drawInBatch(
p_281596_,
(float)p_281586_,
@@ -859,6 +_,7 @@
p_281596_, p_281586_, p_282816_, p_281743_, p_282394_, this.pose.last().pose(), this.bufferSource, Font.DisplayMode.NORMAL, 0, 15728880
);
@@ -850,6 +_,7 @@
CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item");
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered");
crashreportcategory.setDetail("Item Type", () -> String.valueOf(p_281675_.getItem()));
@@ -41,7 +41,7 @@
crashreportcategory.setDetail("Item Components", () -> String.valueOf(p_281675_.getComponents()));
crashreportcategory.setDetail("Item Foil", () -> String.valueOf(p_281675_.hasFoil()));
throw new ReportedException(crashreport);
@@ -879,13 +_,24 @@
@@ -870,13 +_,24 @@
this.renderItemCount(p_282005_, p_283349_, p_282641_, p_282146_, p_282803_);
this.renderItemCooldown(p_283349_, p_282641_, p_282146_);
this.pose.popPose();
@@ -66,7 +66,7 @@
}
public void renderTooltip(Font p_283128_, List<Component> p_282716_, Optional<TooltipComponent> p_281682_, int p_283678_, int p_281696_) {
@@ -895,8 +_,7 @@
@@ -886,8 +_,7 @@
public void renderTooltip(
Font p_362491_, List<Component> p_368544_, Optional<TooltipComponent> p_362815_, int p_366300_, int p_368952_, @Nullable ResourceLocation p_368469_
) {
@@ -76,7 +76,7 @@
this.renderTooltipInternal(p_362491_, list, p_366300_, p_368952_, DefaultTooltipPositioner.INSTANCE, p_368469_);
}
@@ -909,7 +_,22 @@
@@ -900,7 +_,22 @@
}
public void renderComponentTooltip(Font p_282739_, List<Component> p_281832_, int p_282191_, int p_282446_) {
@@ -100,7 +100,7 @@
}
public void renderComponentTooltip(Font p_369090_, List<Component> p_365405_, int p_368143_, int p_366244_, @Nullable ResourceLocation p_364763_) {
@@ -951,11 +_,13 @@
@@ -942,11 +_,13 @@
@Nullable ResourceLocation p_368234_
) {
if (!p_282615_.isEmpty()) {
@@ -115,7 +115,7 @@
if (k > i) {
i = k;
}
@@ -965,18 +_,19 @@
@@ -956,18 +_,19 @@
int i2 = i;
int j2 = j;
@@ -138,7 +138,7 @@
k1 += clienttooltipcomponent1.getHeight(p_282675_) + (l1 == 0 ? 2 : 0);
}
@@ -984,7 +_,7 @@
@@ -975,7 +_,7 @@
for (int k2 = 0; k2 < p_282615_.size(); k2++) {
ClientTooltipComponent clienttooltipcomponent2 = p_282615_.get(k2);
@@ -147,8 +147,8 @@
k1 += clienttooltipcomponent2.getHeight(p_282675_) + (k2 == 0 ? 2 : 0);
}
@@ -1041,6 +_,10 @@
}
@@ -1030,6 +_,10 @@
default:
}
}
+ }
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/DebugScreenOverlay.java
+++ b/net/minecraft/client/gui/components/DebugScreenOverlay.java
@@ -105,9 +_,9 @@
@@ -134,9 +_,9 @@
@Nullable
private CompletableFuture<LevelChunk> serverChunk;
private boolean renderDebug;
@@ -13,7 +13,7 @@
private final LocalSampleLogger frameTimeLogger = new LocalSampleLogger(1);
private final LocalSampleLogger tickTimeLogger = new LocalSampleLogger(TpsDebugDimensions.values().length);
private final LocalSampleLogger pingLogger = new LocalSampleLogger(1);
@@ -135,14 +_,18 @@
@@ -179,14 +_,18 @@
this.clientChunk = null;
}
@@ -35,7 +35,7 @@
this.profilerPieChart.setBottomOffset(10);
if (this.renderFpsCharts) {
int i = p_281427_.guiWidth();
@@ -155,7 +_,9 @@
@@ -199,7 +_,9 @@
this.profilerPieChart.setBottomOffset(this.tpsChart.getFullHeight());
}
@@ -45,7 +45,7 @@
if (this.renderNetworkCharts) {
int l = p_281427_.guiWidth();
int i1 = l / 2;
@@ -171,12 +_,22 @@
@@ -215,12 +_,22 @@
try (Zone zone = profilerfiller.zone("profilerPie")) {
this.profilerPieChart.render(p_281427_);
}
@@ -70,7 +70,7 @@
list.add("");
boolean flag = this.minecraft.getSingleplayerServer() != null;
list.add(
@@ -190,11 +_,18 @@
@@ -234,11 +_,18 @@
+ (this.renderNetworkCharts ? " visible" : " hidden")
);
list.add("For help: press F3 + Q");
@@ -90,7 +90,7 @@
this.renderLines(p_281261_, list, false);
}
@@ -543,6 +_,7 @@
@@ -592,6 +_,7 @@
list.add("");
list.add(ChatFormatting.UNDERLINE + "Targeted Entity");
list.add(String.valueOf(BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType())));
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/toasts/ToastManager.java
+++ b/net/minecraft/client/gui/components/toasts/ToastManager.java
@@ -107,6 +_,7 @@
@@ -127,6 +_,7 @@
}
public void addToast(Toast p_360768_) {
@@ -9,17 +9,17 @@
@Override
public void render(GuiGraphics p_281839_, int p_282704_, int p_283650_, float p_283394_) {
int i = p_281839_.guiWidth();
@@ -99,6 +_,7 @@
@@ -95,6 +_,7 @@
f2 = 1.0F;
}
+ if (renderContents(p_281839_, f2)) {
int k2 = (int)((double)p_281839_.guiWidth() * 0.5);
int l2 = (int)((double)p_281839_.guiHeight() * 0.5);
double d1 = Math.min((double)p_281839_.guiWidth() * 0.75, (double)p_281839_.guiHeight()) * 0.25;
@@ -114,12 +_,14 @@
int l2 = (int)(p_281839_.guiWidth() * 0.5);
int i1 = (int)(p_281839_.guiHeight() * 0.5);
double d0 = Math.min(p_281839_.guiWidth() * 0.75, (double)p_281839_.guiHeight()) * 0.25;
@@ -110,12 +_,14 @@
if (f < 1.0F) {
this.drawProgressBar(p_281839_, i / 2 - j1, l1 - 5, i / 2 + j1, l1 + 5, 1.0F - Mth.clamp(f, 0.0F, 1.0F));
this.drawProgressBar(p_281839_, i / 2 - k1, i2 - 5, i / 2 + k1, i2 + 5, 1.0F - Mth.clamp(f, 0.0F, 1.0F));
}
+ }
@@ -32,7 +32,7 @@
try {
this.reload.checkExceptions();
this.onFinish.accept(Optional.empty());
@@ -127,7 +_,6 @@
@@ -123,7 +_,6 @@
this.onFinish.accept(Optional.of(throwable));
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/Screen.java
+++ b/net/minecraft/client/gui/screens/Screen.java
@@ -200,7 +_,7 @@
@@ -197,7 +_,7 @@
}
public void onClose() {
@@ -39,7 +39,7 @@
}
protected void renderBlurredBackground() {
@@ -454,6 +_,19 @@
@@ -453,6 +_,19 @@
}
public void onFilesDrop(List<Path> p_96591_) {
@@ -33,25 +33,17 @@
.tooltip(tooltip)
.build()
)
@@ -289,6 +_,7 @@
if ((i & -67108864) != 0) {
super.render(p_282860_, p_281753_, p_283539_, p_282628_);
this.logoRenderer.renderLogo(p_282860_, this.width, f);
+ net.minecraftforge.client.ForgeHooksClient.renderMainMenu(this, p_282860_, this.font, this.width, this.height, i);
if (this.splash != null && !this.minecraft.options.hideSplashTexts().get()) {
this.splash.render(p_282860_, this.width, this.font, i);
}
@@ -304,10 +_,18 @@
s = s + I18n.get("menu.modded");
}
- p_282860_.drawString(this.font, s, 2, this.height - 10, 16777215 | i);
+ net.minecraftforge.internal.BrandingControl.forEachLine(true, true, (brd, brdline) ->
+ p_282860_.drawString(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.lineHeight + 1)), 16777215 | i)
+ p_282860_.drawString(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.lineHeight + 1)), 16777215 | i)
+ );
+
+ net.minecraftforge.internal.BrandingControl.forEachAboveCopyrightLine((brd, brdline) ->
+ p_282860_.drawString(this.font, brd, this.width - font.width(brd), this.height - (10 + (brdline + 1) * ( this.font.lineHeight + 1)), 16777215 | i)
+ p_282860_.drawString(this.font, brd, this.width - font.width(brd), this.height - (10 + (brdline + 1) * ( this.font.lineHeight + 1)), 16777215 | i)
+ );
+
if (this.realmsNotificationsEnabled() && f >= 1.0F) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
@@ -38,6 +_,7 @@
@@ -39,6 +_,7 @@
private int maxY = Integer.MIN_VALUE;
private float fade;
private boolean centered;
@@ -8,7 +8,7 @@
public AdvancementTab(
Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, AdvancementNode p_297568_, DisplayInfo p_97150_
@@ -54,6 +_,15 @@
@@ -55,6 +_,15 @@
this.addWidget(this.root, p_297568_.holder());
}
@@ -24,7 +24,7 @@
public AdvancementTabType getType() {
return this.type;
}
@@ -147,8 +_,8 @@
@@ -148,8 +_,8 @@
return null;
} else {
for (AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
@@ -55,6 +55,6 @@
if (this.tabs.size() > 1) {
for (AdvancementTab advancementtab : this.tabs.values()) {
+ if (advancementtab.getPage() == tabPage)
if (advancementtab.isMouseOver(p_281519_, p_283371_, (double)p_283556_, (double)p_282458_)) {
if (advancementtab.isMouseOver(p_281519_, p_283371_, p_283556_, p_282458_)) {
p_282784_.renderTooltip(this.font, advancementtab.getTitle(), p_283556_, p_282458_);
}
@@ -6,7 +6,7 @@
super.render(p_283479_, p_283661_, p_281248_, p_281886_);
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderBackground(this, p_283479_, p_283661_, p_281248_);
p_283479_.pose().pushPose();
p_283479_.pose().translate((float)i, (float)j, 0.0F);
p_283479_.pose().translate(i, j, 0.0F);
Slot slot = this.hoveredSlot;
@@ -117,6 +_,8 @@
this.onStopHovering(slot);
@@ -40,7 +40,7 @@
if (super.mouseClicked(p_97748_, p_97749_, p_97750_)) {
return true;
} else {
- boolean flag = this.minecraft.options.keyPickItem.matchesMouse(p_97750_) && this.minecraft.gameMode.hasInfiniteItems();
- boolean flag = this.minecraft.options.keyPickItem.matchesMouse(p_97750_) && this.minecraft.player.hasInfiniteMaterials();
+ InputConstants.Key mouseKey = InputConstants.Type.MOUSE.getOrCreate(p_97750_);
+ boolean flag = this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey);
Slot slot = this.getHoveredSlot(p_97748_, p_97749_);
@@ -72,7 +72,7 @@
this.quickCraftingType = 2;
}
}
@@ -464,10 +_,13 @@
@@ -461,10 +_,13 @@
@Override
public boolean mouseReleased(double p_97812_, double p_97813_, int p_97814_) {
@@ -86,7 +86,7 @@
int k = -1;
if (slot != null) {
k = slot.index;
@@ -484,7 +_,7 @@
@@ -481,7 +_,7 @@
if (slot2 != null
&& slot2.mayPickup(this.minecraft.player)
&& slot2.hasItem()
@@ -95,7 +95,7 @@
&& AbstractContainerMenu.canItemQuickReplace(slot2, this.lastQuickMoved, true)) {
this.slotClicked(slot2, slot2.index, p_97814_, ClickType.QUICK_MOVE);
}
@@ -548,7 +_,7 @@
@@ -545,7 +_,7 @@
this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT);
} else if (!this.menu.getCarried().isEmpty()) {
@@ -104,7 +104,7 @@
this.slotClicked(slot, k, p_97814_, ClickType.CLONE);
} else {
boolean flag1 = k != -999
@@ -628,9 +_,10 @@
@@ -622,9 +_,10 @@
@Override
public boolean keyPressed(int p_97765_, int p_97766_, int p_97767_) {
@@ -116,7 +116,7 @@
this.onClose();
return true;
} else {
@@ -704,4 +_,11 @@
@@ -698,4 +_,11 @@
super.onClose();
}
@@ -20,7 +20,7 @@
this.menu.items.addAll(p_261591_);
@@ -330,6 +_,35 @@
protected void init() {
if (this.minecraft.gameMode.hasInfiniteItems()) {
if (this.minecraft.player.hasInfiniteMaterials()) {
super.init();
+ this.pages.clear();
+ int tabIndex = 0;
@@ -98,14 +98,14 @@
protected void renderLabels(GuiGraphics p_283168_, int p_281774_, int p_281466_) {
if (selectedTab.showTitle()) {
- p_283168_.drawString(this.font, selectedTab.getDisplayName(), 8, 6, 4210752, false);
+ com.mojang.blaze3d.systems.RenderSystem.disableBlend();
+ com.mojang.blaze3d.opengl.GlStateManager._disableBlend();
+ p_283168_.drawString(this.font, selectedTab.getDisplayName(), 8, 6, selectedTab.getLabelColor(), false);
}
}
@@ -488,7 +_,7 @@
double d0 = p_98531_ - (double)this.leftPos;
double d1 = p_98532_ - (double)this.topPos;
double d0 = p_98531_ - this.leftPos;
double d1 = p_98532_ - this.topPos;
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
@@ -113,7 +113,7 @@
return true;
}
@@ -510,7 +_,7 @@
double d1 = p_98623_ - (double)this.topPos;
double d1 = p_98623_ - this.topPos;
this.scrolling = false;
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
@@ -138,7 +138,7 @@
this.refreshSearchResults();
} else {
@@ -676,7 +_,15 @@
@@ -673,7 +_,15 @@
super.render(p_283000_, p_281317_, p_282770_, p_281295_);
this.effects.render(p_283000_, p_281317_, p_282770_, p_281295_);
@@ -155,7 +155,7 @@
if (this.checkTabHovering(p_283000_, creativemodetab, p_281317_, p_282770_)) {
break;
}
@@ -688,6 +_,7 @@
@@ -685,6 +_,7 @@
p_283000_.renderTooltip(this.font, TRASH_SLOT_TOOLTIP, p_281317_, p_282770_);
}
@@ -163,7 +163,7 @@
this.renderTooltip(p_283000_, p_281317_, p_282770_);
}
@@ -700,7 +_,7 @@
@@ -697,7 +_,7 @@
public List<Component> getTooltipFromContainerItem(ItemStack p_281769_) {
boolean flag = this.hoveredSlot != null && this.hoveredSlot instanceof CreativeModeInventoryScreen.CustomCreativeSlot;
boolean flag1 = selectedTab.getType() == CreativeModeTab.Type.CATEGORY;
@@ -172,7 +172,7 @@
TooltipFlag.Default tooltipflag$default = this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL;
TooltipFlag tooltipflag = flag ? tooltipflag$default.asCreative() : tooltipflag$default;
List<Component> list = p_281769_.getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player, tooltipflag);
@@ -719,7 +_,7 @@
@@ -718,7 +_,7 @@
int i = 1;
for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
@@ -181,7 +181,7 @@
list1.add(i++, creativemodetab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
}
}
@@ -730,7 +_,7 @@
@@ -729,7 +_,7 @@
@Override
protected void renderBg(GuiGraphics p_282663_, float p_282504_, int p_282089_, int p_282249_) {
@@ -190,15 +190,15 @@
if (creativemodetab != selectedTab) {
this.renderTabButton(p_282663_, creativemodetab);
}
@@ -746,6 +_,7 @@
p_282663_.blitSprite(RenderType::guiTextured, resourcelocation, j, k + (int)((float)(i - k - 17) * this.scrollOffs), 12, 15);
@@ -745,6 +_,7 @@
p_282663_.blitSprite(RenderType::guiTextured, resourcelocation, j, k + (int)((i - k - 17) * this.scrollOffs), 12, 15);
}
+ if (currentPage.getVisibleTabs().contains(selectedTab)) //Forge: only display tab selection when the selected tab is on the current page
this.renderTabButton(p_282663_, selectedTab);
if (selectedTab.getType() == CreativeModeTab.Type.INVENTORY) {
InventoryScreen.renderEntityInInventoryFollowsMouse(
@@ -764,7 +_,7 @@
@@ -763,7 +_,7 @@
}
private int getTabX(CreativeModeTab p_260136_) {
@@ -207,7 +207,7 @@
int j = 27;
int k = 27 * i;
if (p_260136_.isAlignedRight()) {
@@ -776,7 +_,7 @@
@@ -775,7 +_,7 @@
private int getTabY(CreativeModeTab p_260181_) {
int i = 0;
@@ -216,7 +216,7 @@
i -= 32;
} else {
i += this.imageHeight;
@@ -804,8 +_,8 @@
@@ -803,8 +_,8 @@
protected void renderTabButton(GuiGraphics p_283590_, CreativeModeTab p_283489_) {
boolean flag = p_283489_ == selectedTab;
@@ -227,15 +227,15 @@
int j = this.leftPos + this.getTabX(p_283489_);
int k = this.topPos - (flag1 ? 28 : -(this.imageHeight - 4));
ResourceLocation[] aresourcelocation;
@@ -815,6 +_,7 @@
@@ -814,6 +_,7 @@
aresourcelocation = flag ? SELECTED_BOTTOM_TABS : UNSELECTED_BOTTOM_TABS;
}
+ com.mojang.blaze3d.systems.RenderSystem.enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
+ com.mojang.blaze3d.opengl.GlStateManager._enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
p_283590_.blitSprite(RenderType::guiTextured, aresourcelocation[Mth.clamp(i, 0, aresourcelocation.length)], j, k, 26, 32);
p_283590_.pose().pushPose();
p_283590_.pose().translate(0.0F, 0.0F, 100.0F);
@@ -856,6 +_,14 @@
@@ -855,6 +_,14 @@
}
}
@@ -250,7 +250,7 @@
@OnlyIn(Dist.CLIENT)
static class CustomCreativeSlot extends Slot {
public CustomCreativeSlot(Container p_98633_, int p_98634_, int p_98635_, int p_98636_) {
@@ -1037,6 +_,22 @@
@@ -1036,6 +_,22 @@
@Override
public boolean mayPickup(Player p_98665_) {
return this.target.mayPickup(p_98665_);
@@ -4,8 +4,8 @@
int l1 = 86 - this.font.width(s);
FormattedText formattedtext = EnchantmentNames.getInstance().getRandomName(this.font, l1);
int i2 = 6839882;
- if ((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.getAbilities().instabuild) {
+ if (((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.getAbilities().instabuild) || this.menu.enchantClue[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
- if ((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) {
+ if (((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) || this.menu.enchantClue[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
p_282430_.blitSprite(RenderType::guiTextured, ENCHANTMENT_SLOT_DISABLED_SPRITE, i1, j + 14 + 19 * l, 108, 19);
p_282430_.blitSprite(RenderType::guiTextured, DISABLED_LEVEL_SPRITES[l], i1 + 1, j + 15 + 19 * l, 16, 16);
p_282430_.drawWordWrap(this.font, formattedtext, j1, j + 16 + 19 * l, l1, (i2 & 16711422) >> 1, false);
@@ -17,7 +17,7 @@
+ {
int l = this.menu.levelClue[j];
int i1 = j + 1;
- if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)p_282491_, (double)p_281953_) && k > 0 && l >= 0 && optional != null) {
- if (this.isHovering(60, 14 + 19 * j, 108, 17, p_282491_, p_281953_) && k > 0 && l >= 0 && optional != null) {
+ if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)p_282491_, (double)p_281953_) && k > 0) {
List<Component> list = Lists.newArrayList();
- list.add(Component.translatable("container.enchant.clue", Enchantment.getFullname(optional.get(), l)).withStyle(ChatFormatting.WHITE));
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
+++ b/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
@@ -25,7 +_,7 @@
@@ -22,7 +_,7 @@
case ClientActivePlayersTooltip.ActivePlayersTooltip clientactiveplayerstooltip$activeplayerstooltip -> new ClientActivePlayersTooltip(
clientactiveplayerstooltip$activeplayerstooltip
);
clientactiveplayerstooltip$activeplayerstooltip
);
- default -> throw new IllegalArgumentException("Unknown TooltipComponent");
+ default -> net.minecraftforge.client.gui.ClientTooltipComponentManager.createClientTooltipComponent(p_169951_);
});
@@ -11,7 +11,7 @@
+ .bounds(0, 0, 75 + 20 /* Forge: Add space */, 20)
.createNarration(
p_342179_ -> p_343088_.isUnbound()
? Component.translatable("narrator.controls.unbound", p_343976_)
? Component.translatable("narrator.controls.unbound", p_343976_)
@@ -158,7 +_,7 @@
)
.build();
@@ -6,6 +6,6 @@
p_100014_.setSelected(null);
- p_100015_.forEach(
+ p_100015_.filter(PackSelectionModel.Entry::notHidden).forEach(
p_374582_ -> {
p_389318_ -> {
TransferableSelectionList.PackEntry transferableselectionlist$packentry1 = new TransferableSelectionList.PackEntry(
this.minecraft, p_100014_, p_374582_
this.minecraft, p_100014_, p_389318_
@@ -1,14 +1,14 @@
--- a/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
+++ b/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
@@ -168,6 +_,7 @@
) {
queueLoadScreen(p_369292_, PREPARING_WORLD_DATA);
PackRepository packrepository = new PackRepository(new ServerPacksSource(p_369292_.directoryValidator()));
@@ -171,6 +_,7 @@
WorldDataConfiguration worlddataconfiguration = SharedConstants.IS_RUNNING_IN_IDE
? new WorldDataConfiguration(new DataPackConfig(List.of("vanilla", "tests"), List.of()), FeatureFlags.DEFAULT_FLAGS)
: WorldDataConfiguration.DEFAULT;
+ net.minecraftforge.event.ForgeEventFactory.addPackFindersServer(packrepository::addPackFinder);
WorldLoader.InitConfig worldloader$initconfig = createDefaultLoadConfig(packrepository, WorldDataConfiguration.DEFAULT);
WorldLoader.InitConfig worldloader$initconfig = createDefaultLoadConfig(packrepository, worlddataconfiguration);
CompletableFuture<WorldCreationContext> completablefuture = WorldLoader.load(
worldloader$initconfig,
@@ -468,7 +_,7 @@
@@ -471,7 +_,7 @@
if (p_269627_) {
p_270552_.accept(this.uiState.getSettings().dataConfiguration());
} else {
@@ -17,7 +17,7 @@
}
},
Component.translatable("dataPack.validation.failed"),
@@ -582,6 +_,7 @@
@@ -585,6 +_,7 @@
if (path != null) {
if (this.tempDataPackRepository == null) {
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
@@ -1,7 +1,7 @@
--- a/net/minecraft/client/model/geom/LayerDefinitions.java
+++ b/net/minecraft/client/model/geom/LayerDefinitions.java
@@ -464,6 +_,7 @@
builder.put(ModelLayers.createHangingSignModelName(p_374591_, hangingsignrenderer$attachmenttype), layerdefinition55);
@@ -497,6 +_,7 @@
builder.put(ModelLayers.createHangingSignModelName(p_374591_, hangingsignrenderer$attachmenttype), layerdefinition60);
}
});
+ net.minecraftforge.client.ForgeHooksClient.loadLayerDefinitions(builder);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/model/geom/ModelLayers.java
+++ b/net/minecraft/client/model/geom/ModelLayers.java
@@ -308,15 +_,18 @@
@@ -330,15 +_,18 @@
}
public static ModelLayerLocation createStandingSignModelName(WoodType p_171292_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientChunkCache.java
+++ b/net/minecraft/client/multiplayer/ClientChunkCache.java
@@ -63,6 +_,7 @@
@@ -64,6 +_,7 @@
int i = this.storage.getIndex(p_298665_.x, p_298665_.z);
LevelChunk levelchunk = this.storage.getChunk(i);
if (isValidChunk(levelchunk, p_298665_.x, p_298665_.z)) {
@@ -8,7 +8,7 @@
this.storage.drop(i, levelchunk);
}
}
@@ -124,6 +_,7 @@
@@ -125,6 +_,7 @@
}
this.level.onChunkLoaded(chunkpos);
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/multiplayer/ClientConfigurationPacketListenerImpl.java
+++ b/net/minecraft/client/multiplayer/ClientConfigurationPacketListenerImpl.java
@@ -142,6 +_,7 @@
);
this.connection.send(ServerboundFinishConfigurationPacket.INSTANCE);
this.connection.setupOutboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(registryaccess$frozen)));
@@ -147,6 +_,7 @@
return true;
}
}));
+ net.minecraftforge.common.ForgeHooks.handleClientConfigurationComplete(this.connection);
}
@@ -1,14 +1,14 @@
--- a/net/minecraft/client/multiplayer/ClientLevel.java
+++ b/net/minecraft/client/multiplayer/ClientLevel.java
@@ -123,6 +_,7 @@
p_194170_.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache(p_194181_ -> this.calculateBlockTint(p_194181_, BiomeColors.GRASS_COLOR_RESOLVER)));
p_194170_.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache(p_194177_ -> this.calculateBlockTint(p_194177_, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
p_194170_.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache(p_194168_ -> this.calculateBlockTint(p_194168_, BiomeColors.WATER_COLOR_RESOLVER)));
+ net.minecraftforge.client.ColorResolverManager.registerBlockTintCaches(ClientLevel.this, p_194170_);
@@ -126,6 +_,7 @@
p_389331_.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache(p_194177_ -> this.calculateBlockTint(p_194177_, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
p_389331_.put(BiomeColors.DRY_FOLIAGE_COLOR_RESOLVER, new BlockTintCache(p_389335_ -> this.calculateBlockTint(p_389335_, BiomeColors.DRY_FOLIAGE_COLOR_RESOLVER)));
p_389331_.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache(p_194168_ -> this.calculateBlockTint(p_194168_, BiomeColors.WATER_COLOR_RESOLVER)));
+ net.minecraftforge.client.ColorResolverManager.registerBlockTintCaches(ClientLevel.this, p_389331_);
});
private final ClientChunkCache chunkSource;
private final Deque<Runnable> lightUpdateQueue = Queues.newArrayDeque();
@@ -131,6 +_,8 @@
@@ -134,6 +_,8 @@
private final int seaLevel;
private boolean tickDayTime;
private static final Set<Item> MARKER_PARTICLE_ITEMS = Set.of(Items.BARRIER, Items.LIGHT);
@@ -17,7 +17,7 @@
public void handleBlockChangedAck(int p_233652_) {
this.blockStatePredictionHandler.endPredictionsUpTo(p_233652_, this);
@@ -197,6 +_,8 @@
@@ -200,6 +_,8 @@
this.serverSimulationDistance = p_364305_;
this.updateSkyBrightness();
this.prepareWeather();
@@ -26,7 +26,7 @@
}
public void queueLightUpdate(Runnable p_194172_) {
@@ -279,6 +_,7 @@
@@ -282,6 +_,7 @@
p_104640_.setOldPosAndRot();
p_104640_.tickCount++;
Profiler.get().push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(p_104640_.getType()).toString());
@@ -34,7 +34,7 @@
p_104640_.tick();
Profiler.get().pop();
@@ -330,8 +_,10 @@
@@ -333,8 +_,10 @@
}
public void addEntity(Entity p_104741_) {
@@ -45,7 +45,7 @@
}
public void removeEntity(int p_171643_, Entity.RemovalReason p_171644_) {
@@ -502,6 +_,12 @@
@@ -516,6 +_,12 @@
float p_263349_,
long p_263408_
) {
@@ -55,24 +55,24 @@
+ p_263417_ = event.getSource();
+ p_263416_ = event.getNewVolume();
+ p_263349_ = event.getNewPitch();
if (p_263381_ == this.minecraft.player) {
if (p_394722_ == this.minecraft.player) {
this.playSound(p_263372_, p_263404_, p_263365_, p_263335_.value(), p_263417_, p_263416_, p_263349_, false, p_263408_);
}
@@ -511,6 +_,12 @@
@@ -525,6 +_,12 @@
public void playSeededSound(
@Nullable Player p_263514_, Entity p_263536_, Holder<SoundEvent> p_263518_, SoundSource p_263487_, float p_263538_, float p_263524_, long p_263509_
@Nullable Entity p_263536_, Entity p_396496_, Holder<SoundEvent> p_263518_, SoundSource p_263487_, float p_263538_, float p_263524_, long p_263509_
) {
+ var event = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAtEntity(p_263536_, p_263518_, p_263487_, p_263538_, p_263524_);
+ var event = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAtEntity(this.minecraft.level, p_263536_, p_263518_, p_263487_, p_263538_, p_263524_);
+ if (event.isCanceled() || event.getSound() == null) return;
+ p_263518_ = event.getSound();
+ p_263487_ = event.getSource();
+ p_263538_ = event.getNewVolume();
+ p_263524_ = event.getNewPitch();
if (p_263514_ == this.minecraft.player) {
this.minecraft.getSoundManager().play(new EntityBoundSoundInstance(p_263518_.value(), p_263487_, p_263538_, p_263524_, p_263536_, p_263509_));
if (p_263536_ == this.minecraft.player) {
this.minecraft.getSoundManager().play(new EntityBoundSoundInstance(p_263518_.value(), p_263487_, p_263538_, p_263524_, p_396496_, p_263509_));
}
@@ -953,6 +_,24 @@
return this.seaLevel;
@@ -975,6 +_,16 @@
this.connection.registerForCleaning(p_396040_);
}
+ @Override
@@ -84,19 +84,11 @@
+ public net.minecraftforge.client.model.data.ModelDataManager getModelDataManager() {
+ return modelDataManager;
+ }
+
+ @Override
+ public float getShade(float normalX, float normalY, float normalZ, boolean shade) {
+ boolean constantAmbientLight = this.effects().constantAmbientLight();
+ if (!shade)
+ return constantAmbientLight ? 0.9F : 1.0F;
+ return net.minecraftforge.client.model.lighting.QuadLighter.calculateShade(normalX, normalY, normalZ, constantAmbientLight);
+ }
+
@OnlyIn(Dist.CLIENT)
public static class ClientLevelData implements WritableLevelData {
private final boolean hardcore;
@@ -1041,6 +_,7 @@
@@ -1063,6 +_,7 @@
}
public void setDifficulty(Difficulty p_104852_) {
@@ -104,7 +96,7 @@
this.difficulty = p_104852_;
}
@@ -1084,6 +_,12 @@
@@ -1105,6 +_,12 @@
break;
default:
}
@@ -117,7 +109,7 @@
}
public void onTrackingEnd(Entity p_171716_) {
@@ -1097,6 +_,15 @@
@@ -1117,6 +_,15 @@
ClientLevel.this.dragonParts.removeAll(Arrays.asList(enderdragon.getSubEntities()));
break;
default:
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientPacketListener.java
+++ b/net/minecraft/client/multiplayer/ClientPacketListener.java
@@ -452,6 +_,7 @@
@@ -477,6 +_,7 @@
this.minecraft.debugRenderer.clear();
this.minecraft.player.resetPos();
@@ -8,7 +8,7 @@
this.minecraft.player.setId(p_105030_.playerId());
this.level.addEntity(this.minecraft.player);
this.minecraft.player.input = new KeyboardInput(this.minecraft.options);
@@ -1249,6 +_,8 @@
@@ -1263,6 +_,8 @@
localplayer1.getAttributes().assignBaseValues(localplayer.getAttributes());
}
@@ -17,19 +17,16 @@
this.level.addEntity(localplayer1);
localplayer1.input = new KeyboardInput(this.minecraft.options);
this.minecraft.gameMode.adjustPlayer(localplayer1);
@@ -1393,10 +_,7 @@
@@ -1407,7 +_,7 @@
PacketUtils.ensureRunningOnSameThread(p_104976_, this, this.minecraft);
BlockPos blockpos = p_104976_.getPos();
this.minecraft.level.getBlockEntity(blockpos, p_104976_.getType()).ifPresent(p_325478_ -> {
- CompoundTag compoundtag = p_104976_.getTag();
- if (!compoundtag.isEmpty()) {
- p_325478_.loadWithComponents(compoundtag, this.registryAccess);
- }
+ p_325478_.onDataPacket(connection, p_104976_, this.registryAccess);
if (p_325478_ instanceof CommandBlockEntity && this.minecraft.screen instanceof CommandBlockEditScreen) {
this.minecraft.level.getBlockEntity(blockpos, p_104976_.getType()).ifPresent(p_389343_ -> {
- p_389343_.loadWithComponents(p_104976_.getTag(), this.registryAccess);
+ p_389343_.onDataPacket(connection, p_104976_, this.registryAccess);
if (p_389343_ instanceof CommandBlockEntity && this.minecraft.screen instanceof CommandBlockEditScreen) {
((CommandBlockEditScreen)this.minecraft.screen).updateGui();
@@ -1557,7 +_,9 @@
}
@@ -1567,7 +_,9 @@
@Override
public void handleCommands(ClientboundCommandsPacket p_104990_) {
PacketUtils.ensureRunningOnSameThread(p_104990_, this, this.minecraft);
@@ -40,7 +37,7 @@
}
@Override
@@ -1658,6 +_,7 @@
@@ -1668,6 +_,7 @@
if (this.minecraft.screen instanceof RecipeUpdateListener recipeupdatelistener) {
recipeupdatelistener.recipesUpdated();
}
@@ -48,7 +45,7 @@
}
@Override
@@ -1696,6 +_,8 @@
@@ -1706,6 +_,8 @@
this.fuelValues = FuelValues.vanillaBurnTimes(this.registryAccess, this.enabledFeatures);
List<ItemStack> list1 = List.copyOf(CreativeModeTabs.searchTab().getDisplayItems());
this.searchTrees.updateCreativeTags(list1);
@@ -57,7 +54,7 @@
}
@Override
@@ -2530,6 +_,8 @@
@@ -2548,6 +_,8 @@
}
public void sendChat(String p_249888_) {
@@ -66,7 +63,7 @@
Instant instant = Instant.now();
long i = Crypt.SaltSupplier.getLong();
LastSeenMessagesTracker.Update lastseenmessagestracker$update = this.lastSeenMessages.generateAndApplyUpdate();
@@ -2538,6 +_,7 @@
@@ -2556,6 +_,7 @@
}
public void sendCommand(String p_250092_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/MultiPlayerGameMode.java
+++ b/net/minecraft/client/multiplayer/MultiPlayerGameMode.java
@@ -107,6 +_,7 @@
@@ -110,6 +_,7 @@
}
public boolean destroyBlock(BlockPos p_105268_) {
@@ -8,7 +8,7 @@
if (this.minecraft.player.blockActionRestricted(this.minecraft.level, p_105268_, this.localPlayerMode)) {
return false;
} else {
@@ -121,9 +_,8 @@
@@ -124,9 +_,8 @@
} else if (blockstate.isAir()) {
return false;
} else {
@@ -19,7 +19,7 @@
if (flag) {
block.destroy(level, p_105268_, blockstate);
}
@@ -144,6 +_,7 @@
@@ -147,6 +_,7 @@
BlockState blockstate = this.minecraft.level.getBlockState(p_105270_);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, p_105270_, blockstate, 1.0F);
this.startPrediction(this.minecraft.level, p_233757_ -> {
@@ -27,7 +27,7 @@
this.destroyBlock(p_105270_);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, p_105270_, p_105271_, p_233757_);
});
@@ -153,15 +_,18 @@
@@ -156,15 +_,18 @@
this.connection
.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, this.destroyBlockPos, p_105271_));
}
@@ -46,7 +46,7 @@
if (flag && blockstate1.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), p_105270_) >= 1.0F) {
this.destroyBlock(p_105270_);
} else {
@@ -172,6 +_,7 @@
@@ -175,6 +_,7 @@
this.destroyTicks = 0.0F;
this.minecraft.level.destroyBlockProgress(this.minecraft.player.getId(), this.destroyBlockPos, this.getDestroyStage());
}
@@ -54,7 +54,7 @@
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, p_105270_, p_105271_, p_233728_);
});
@@ -204,6 +_,7 @@
@@ -207,6 +_,7 @@
BlockState blockstate1 = this.minecraft.level.getBlockState(p_105284_);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, p_105284_, blockstate1, 1.0F);
this.startPrediction(this.minecraft.level, p_233753_ -> {
@@ -62,7 +62,7 @@
this.destroyBlock(p_105284_);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, p_105284_, p_105285_, p_233753_);
});
@@ -216,7 +_,7 @@
@@ -219,7 +_,7 @@
} else {
this.destroyProgress = this.destroyProgress + blockstate.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), p_105284_);
if (this.destroyTicks % 4.0F == 0.0F) {
@@ -71,7 +71,7 @@
this.minecraft
.getSoundManager()
.play(
@@ -233,6 +_,7 @@
@@ -236,6 +_,7 @@
this.destroyTicks++;
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, p_105284_, blockstate, Mth.clamp(this.destroyProgress, 0.0F, 1.0F));
@@ -79,7 +79,7 @@
if (this.destroyProgress >= 1.0F) {
this.isDestroying = false;
this.startPrediction(this.minecraft.level, p_233739_ -> {
@@ -271,7 +_,7 @@
@@ -274,7 +_,7 @@
private boolean sameDestroyTarget(BlockPos p_105282_) {
ItemStack itemstack = this.minecraft.player.getMainHandItem();
@@ -88,7 +88,7 @@
}
private void ensureHasSentCarriedItem() {
@@ -299,12 +_,23 @@
@@ -302,12 +_,23 @@
private InteractionResult performUseItemOn(LocalPlayer p_233747_, InteractionHand p_233748_, BlockHitResult p_233749_) {
BlockPos blockpos = p_233749_.getBlockPos();
ItemStack itemstack = p_233747_.getItemInHand(p_233748_);
@@ -114,7 +114,7 @@
BlockState blockstate = this.minecraft.level.getBlockState(blockpos);
if (!this.connection.isFeatureEnabled(blockstate.getBlock().requiredFeatures())) {
return InteractionResult.FAIL;
@@ -325,8 +_,10 @@
@@ -328,8 +_,10 @@
}
}
@@ -125,9 +125,9 @@
+ }
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (!itemstack.isEmpty() && !p_233747_.getCooldowns().isOnCooldown(itemstack))) {
InteractionResult interactionresult2;
if (this.localPlayerMode.isCreative()) {
if (p_233747_.hasInfiniteMaterials()) {
int i = itemstack.getCount();
@@ -360,6 +_,11 @@
@@ -363,6 +_,11 @@
mutableobject.setValue(InteractionResult.PASS);
return serverbounduseitempacket;
} else {
@@ -139,7 +139,7 @@
InteractionResult interactionresult = itemstack.use(this.minecraft.level, p_233722_, p_233723_);
ItemStack itemstack1;
if (interactionresult instanceof InteractionResult.Success interactionresult$success) {
@@ -370,6 +_,9 @@
@@ -373,6 +_,9 @@
if (itemstack1 != itemstack) {
p_233722_.setItemInHand(p_233723_, itemstack1);
@@ -149,7 +149,7 @@
}
mutableobject.setValue(interactionresult);
@@ -401,6 +_,10 @@
@@ -404,6 +_,10 @@
public InteractionResult interact(Player p_105227_, Entity p_105228_, InteractionHand p_105229_) {
this.ensureHasSentCarriedItem();
this.connection.send(ServerboundInteractPacket.createInteractionPacket(p_105228_, p_105227_.isShiftKeyDown(), p_105229_));
@@ -160,7 +160,7 @@
return (InteractionResult)(this.localPlayerMode == GameType.SPECTATOR ? InteractionResult.PASS : p_105227_.interactOn(p_105228_, p_105229_));
}
@@ -408,6 +_,10 @@
@@ -411,6 +_,10 @@
this.ensureHasSentCarriedItem();
Vec3 vec3 = p_105233_.getLocation().subtract(p_105232_.getX(), p_105232_.getY(), p_105232_.getZ());
this.connection.send(ServerboundInteractPacket.createInteractionPacket(p_105232_, p_105231_.isShiftKeyDown(), p_105234_, vec3));
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ServerData.java
+++ b/net/minecraft/client/multiplayer/ServerData.java
@@ -34,6 +_,7 @@
@@ -37,6 +_,7 @@
private byte[] iconBytes;
private ServerData.Type type;
private ServerData.State state = ServerData.State.INITIAL;
@@ -11,7 +11,7 @@
private CompletableFuture<SearchTree<RecipeCollection>> recipeSearch = CompletableFuture.completedFuture(SearchTree.empty());
private final Map<SessionSearchTrees.Key, Runnable> reloaders = new IdentityHashMap<>();
@@ -92,44 +_,52 @@
@@ -90,44 +_,52 @@
}
public void updateCreativeTags(List<ItemStack> p_344581_) {
@@ -53,11 +53,11 @@
+ CompletableFuture<?> completablefuture = this.creativeSearch.getOrDefault(entry.getValue(), EMPTY);
+ this.creativeSearch.put(entry.getValue(), CompletableFuture.supplyAsync(
() -> new FullTextSearchTree<>(
p_345254_ -> getTooltipLines(Stream.of(p_345254_), item$tooltipcontext, tooltipflag),
p_344415_ -> p_344415_.getItemHolder().unwrapKey().map(ResourceKey::location).stream(),
- p_342500_
+ items
),
p_345254_ -> getTooltipLines(Stream.of(p_345254_), item$tooltipcontext, tooltipflag),
p_344415_ -> p_344415_.getItemHolder().unwrapKey().map(ResourceKey::location).stream(),
- p_342500_
+ items
),
Util.backgroundExecutor()
- );
+ ));
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/chat/ChatListener.java
+++ b/net/minecraft/client/multiplayer/chat/ChatListener.java
@@ -118,7 +_,9 @@
@@ -123,7 +_,9 @@
Instant instant = Instant.now();
this.handleMessage(null, () -> {
Component component = p_251256_.decorate(p_250375_);
@@ -11,7 +11,7 @@
this.narrateChatMessage(p_251256_, p_250375_);
this.logSystemMessage(component, instant);
this.previousMessageTime = Util.getMillis();
@@ -137,12 +_,16 @@
@@ -142,12 +_,16 @@
MessageSignature messagesignature = p_249430_.signature();
FilterMask filtermask = p_249430_.filterMask();
if (filtermask.isEmpty()) {
@@ -30,7 +30,7 @@
this.narrateChatMessage(p_251766_, component);
}
}
@@ -175,6 +_,8 @@
@@ -180,6 +_,8 @@
public void handleSystemMessage(Component p_240522_, boolean p_240642_) {
if (!this.minecraft.options.hideMatchedNames().get() || !this.minecraft.isBlocked(this.guessChatUUID(p_240522_))) {
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/particle/FlyTowardsPositionParticle.java
+++ b/net/minecraft/client/particle/FlyTowardsPositionParticle.java
@@ -104,6 +_,7 @@
this.x = this.xStart + this.xd * (double)f;
this.y = this.yStart + this.yd * (double)f - (double)(f1 * 1.2F);
this.z = this.zStart + this.zd * (double)f;
this.x = this.xStart + this.xd * f;
this.y = this.yStart + this.yd * f - f1 * 1.2F;
this.z = this.zStart + this.zd * f;
+ this.setPos(this.x, this.y, this.z); // FORGE: update the particle's bounding box
}
}
@@ -17,5 +17,5 @@
+ }
+
@OnlyIn(Dist.CLIENT)
public static record LifetimeAlpha(float startAlpha, float endAlpha, float startAtNormalizedAge, float endAtNormalizedAge) {
public record LifetimeAlpha(float startAlpha, float endAlpha, float startAtNormalizedAge, float endAtNormalizedAge) {
public static final Particle.LifetimeAlpha ALWAYS_OPAQUE = new Particle.LifetimeAlpha(1.0F, 1.0F, 0.0F, 1.0F);
@@ -1,13 +1,12 @@
--- a/net/minecraft/client/particle/ParticleEngine.java
+++ b/net/minecraft/client/particle/ParticleEngine.java
@@ -72,11 +_,11 @@
@@ -72,10 +_,10 @@
private static final int MAX_PARTICLES_PER_LAYER = 16384;
private static final List<ParticleRenderType> RENDER_ORDER = List.of(ParticleRenderType.TERRAIN_SHEET, ParticleRenderType.PARTICLE_SHEET_OPAQUE, ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT);
protected ClientLevel level;
- private final Map<ParticleRenderType, Queue<Particle>> particles = Maps.newIdentityHashMap();
+ private final Map<ParticleRenderType, Queue<Particle>> particles = Maps.newTreeMap(net.minecraftforge.client.ForgeHooksClient.makeParticleRenderTypeComparator(RENDER_ORDER));
private final Queue<TrackingEmitter> trackingEmitters = Queues.newArrayDeque();
private final TextureManager textureManager;
private final RandomSource random = RandomSource.create();
- private final Int2ObjectMap<ParticleProvider<?>> providers = new Int2ObjectOpenHashMap<>();
+ private final Map<ResourceLocation, ParticleProvider<?>> providers = new java.util.HashMap<>();
@@ -15,7 +14,7 @@
private final Map<ResourceLocation, ParticleEngine.MutableSpriteSet> spriteSets = Maps.newHashMap();
private final TextureAtlas textureAtlas;
@@ -205,10 +_,14 @@
this.register(ParticleTypes.BLOCK_CRUMBLE, new TerrainParticle.CrumblingProvider());
this.register(ParticleTypes.FIREFLY, FireflyParticle.FireflyProvider::new);
}
+ /** @deprecated Register via {@link net.minecraftforge.client.event.RegisterParticleProvidersEvent} */
@@ -66,7 +65,7 @@
+
+ public void render(Camera p_107340_, float p_107341_, MultiBufferSource.BufferSource p_377798_, @Nullable net.minecraft.client.renderer.culling.Frustum frustum) {
+ for (ParticleRenderType particlerendertype : this.particles.keySet()) { // Forge: allow custom IParticleRenderType's
+ if (particlerendertype == ParticleRenderType.NO_RENDER) continue;
+ if (particlerendertype.renderType() == null) continue;
Queue<Particle> queue = this.particles.get(particlerendertype);
if (queue != null && !queue.isEmpty()) {
- renderParticleType(p_107340_, p_107341_, p_377798_, particlerendertype, queue);
@@ -139,7 +138,7 @@
BlockState blockstate = this.level.getBlockState(p_107368_);
if (blockstate.getRenderShape() != RenderShape.INVISIBLE && blockstate.shouldSpawnTerrainParticles()) {
@@ -558,7 +_,7 @@
d0 = (double)i + aabb.maxX + 0.1F;
d0 = i + aabb.maxX + 0.1F;
}
- this.add(new TerrainParticle(this.level, d0, d1, d2, 0.0, 0.0, 0.0, blockstate, p_107368_).setPower(0.2F).scale(0.6F));
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/particle/PortalParticle.java
+++ b/net/minecraft/client/particle/PortalParticle.java
@@ -80,6 +_,7 @@
this.x = this.xStart + this.xd * (double)f2;
this.y = this.yStart + this.yd * (double)f2 + (double)(1.0F - f);
this.z = this.zStart + this.zd * (double)f2;
this.x = this.xStart + this.xd * f2;
this.y = this.yStart + this.yd * f2 + (1.0F - f);
this.z = this.zStart + this.zd * f2;
+ this.setPos(this.x, this.y, this.z); // FORGE: update the particle's bounding box
}
}
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/particle/ReversePortalParticle.java
+++ b/net/minecraft/client/particle/ReversePortalParticle.java
@@ -31,6 +_,7 @@
this.x = this.x + this.xd * (double)f;
this.y = this.y + this.yd * (double)f;
this.z = this.z + this.zd * (double)f;
this.x = this.x + this.xd * f;
this.y = this.y + this.yd * f;
this.z = this.z + this.zd * f;
+ this.setPos(this.x, this.y, this.z); // FORGE: update the particle's bounding box
}
}
@@ -7,22 +7,21 @@
- if (!p_172458_.is(Blocks.GRASS_BLOCK)) {
+ if (net.minecraftforge.client.extensions.common.IClientBlockExtensions.of(p_172458_).areBreakingParticlesTinted(p_172458_, p_172451_, p_172459_)) {
int i = Minecraft.getInstance().getBlockColors().getColor(p_172458_, p_172451_, p_172459_, 0);
this.rCol *= (float)(i >> 16 & 0xFF) / 255.0F;
this.gCol *= (float)(i >> 8 & 0xFF) / 255.0F;
@@ -97,9 +_,15 @@
this.rCol *= (i >> 16 & 0xFF) / 255.0F;
this.gCol *= (i >> 8 & 0xFF) / 255.0F;
@@ -97,8 +_,14 @@
) {
BlockState blockstate = p_331600_.getState();
return !blockstate.isAir() && !blockstate.is(Blocks.MOVING_PISTON) && blockstate.shouldSpawnTerrainParticles()
- ? new TerrainParticle(p_334810_, p_328897_, p_329583_, p_331123_, p_333546_, p_335782_, p_335068_, blockstate)
+ ? (TerrainParticle)new TerrainParticle(p_334810_, p_328897_, p_329583_, p_331123_, p_333546_, p_335782_, p_335068_, blockstate).updateSprite(blockstate, p_331600_.getPos())
: null;
}
+ }
+
+ public Particle updateSprite(BlockState state, BlockPos pos) { //FORGE: we cannot assume that the x y z of the particles match the block pos of the block.
+ if (pos != null) // There are cases where we are not able to obtain the correct source pos, and need to fallback to the non-model data version
+ this.setSprite(Minecraft.getInstance().getBlockRenderer().getBlockModelShaper().getTexture(state, level, pos));
+ this.setSprite(Minecraft.getInstance().getBlockRenderer().getBlockModelShaper().getParticleIcon(state, level, pos));
+ return this;
+ }
}
@OnlyIn(Dist.CLIENT)
public static class CrumblingProvider implements ParticleProvider<BlockParticleOption> {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/player/AbstractClientPlayer.java
+++ b/net/minecraft/client/player/AbstractClientPlayer.java
@@ -91,6 +_,6 @@
@@ -86,6 +_,6 @@
}
}
Loaded 100 of 930 files, more files were not shown because too many files have changed in this diff. Show more