Compare commits

...
66 Commits
Author SHA1 Message Date
LexManos 617ecb7ad3 43.2 Recommended Build. 2022-12-07 23:20:28 -08:00
Su5eD dd8239c255 Allow discovering services from the mods folder that use java's modular definition. (#9143) 2022-11-30 14:50:30 -08:00
Brennan Ward bdddc8c5d4 Make Datapack Registries support ICondition(s) (#9113) 2022-11-30 14:45:00 -08:00
Marc Hermans c1c619a109 Enable additional build types to handle pull request validation. (#9159) 2022-11-30 14:08:05 -08:00
sciwhiz12 f7eea35cb9 Check source permission level before selector permission (#9147)
In some situations, such as execution of a function by an advancement as
part of its reward, a command source stack may have a backing source of
a ServerPlayer which may lack the entity selector permission and have an
explicit permission level that should allow the use of entity selectors,
through CommandSourceStack#withPermission.

We now check if the permission level of the command source stack is
sufficient for entity selectors _before_ checking if the source is a
player and if they have the requisite permission.

This means that an operator permission level of 2 will always override
the Forge entity selector permission.

Fixes #9137
2022-11-30 14:07:18 -08:00
J.T. McQuigg a2434e1607 Fix fires spreading too/igniting custom portal frames. (#9142) 2022-11-30 14:06:22 -08:00
Minecraftschurli b806ecd0ff Add supplier to FlowerBlock so it works with custom MobEffects (#9139) 2022-11-30 14:04:15 -08:00
KnightMiner 8358b800e9 Fix some logical bugs related to the Grindstone Event (#9089) 2022-11-30 14:00:59 -08:00
Néstor Amador b25a092cf1 Call baked model's getModelData before getRenderTypes (#9163) 2022-11-28 17:53:19 +01:00
Jonathan Coates d812fdd0a3 Make Util.memoize thread-safe (#9155) 2022-11-23 09:18:04 +01:00
Néstor Amador 2d3ee8a228 Rendering tweaks and fixes: Part 4 (#9065) 2022-11-23 09:17:43 +01:00
matyrobbrt 97a9ca65f1 Fix Transformation loading PoseStack (#9083) 2022-11-21 20:49:41 +01:00
Néstor Amador f043fbbc51 Add simple block appearance API (#9066) 2022-11-21 20:48:30 +01:00
SizableShrimp a19ab3a8d4 Fix invalidated modded packets when on LAN (#9157) 2022-11-20 18:34:21 -08:00
Dennis C bc0517a404 Improve extensibility of DetectorRailBlock and PoweredRailBlock (#9130) 2022-11-08 12:18:48 -08:00
Su5eD dc9c0d7e35 Fix launch handler minecraft classpath locator (#9120) 2022-11-08 12:17:48 -08:00
matyrobbrt 1a2207b3b2 Add HitResult to EntityTeleportEvent$EnderPearl (#9135) 2022-11-08 12:17:18 -08:00
sciwhiz12 84ab9764e3 Throw aggregate exception for erroneous registry event dispatch (#9111)
This means that exceptions occurring during the dispatch of the registry
events, such as those from the suppliers of RegistryObjects, properly
cause a crash rather than merely being logged and allowing the game to
reach the main menu.

Fixes #8720
2022-11-08 12:17:00 -08:00
Nexus-Dino bef68991f0 Add missing semi-colon near the Dist import statement in example mod. 2022-11-08 12:16:49 -08:00
Nexus-Dino 526c13d662 Fix ClientModEvents example not subscribing to client-sided events (#9097) 2022-10-21 13:22:57 -07:00
matyrobbrt 67ffb78c23 Use GitHub action to lock issues with the spam label (#9087) 2022-10-21 13:22:31 -07:00
sciwhiz12 8f407c3a22 Remove structures slave map to Feature registry (#9091) 2022-10-21 13:22:18 -07:00
Dennis C 8980252e16 Improve logging of missing or unsupported dependencies (#9104) 2022-10-21 13:21:49 -07:00
DBotThePony 3baee80485 [1.19.x] Fix ValueSpec caching the return value incorrectly (#9046) 2022-10-14 17:43:21 +01:00
eerussianguy ca9599bb4d [1.19.x] Add event for registering spawn placements, and modifying existing (#9024) 2022-10-14 17:39:14 +01:00
eerussianguy 051db7907a [1.19.x] Add event for items being stacked or swapped in a GUI. (#9050) 2022-10-14 17:30:12 +01:00
Magnus Jensen bdba5ef2d3 [1.19.x] Fix PlayerInteractEvent.EntityInteractSpecific not cancelling on a server (#9079) 2022-10-14 17:18:17 +01:00
DBotThePony 838b9c0eda Fix canceling phantom spawns preventing any further attempts that tick. (#9041) 2022-10-13 11:40:56 -07:00
Magnus Jensen be584c54aa Rename fluid type milk translation keys (#9077) 2022-10-12 12:54:34 -07:00
ChampionAsh5357 1b3640b42d Fix minecart speed with water (#9076) 2022-10-12 12:51:13 -07:00
Sara Freimer be5dab5801 Add a cancellable event that gets fired when a Totem of Undying is used (#9069) 2022-10-12 12:46:08 -07:00
Marc Hermans aae628cd18 Fix performance issue and logging when resource caching is enabled (#9029) 2022-10-12 12:00:25 -07:00
Magnus Jensen e7bd08649f Fix NPE when feeding wolves and cats (#9074) 2022-10-07 19:55:40 -07:00
Paint_Ninja e1017a4c7e Fix logically breaking change to ForgeConfigSpec.Builder#comment where modders could not add a empty line to the start of comments. (#9061) 2022-10-03 11:50:32 -07:00
SizableShrimp 6f8ba9d295 Fix ServiceLoader bug
Signed-off-by: SizableShrimp <[email protected]>
2022-09-29 22:11:12 -07:00
SizableShrimp ac94478ae7 Fix ClientChatReceivedEvent for system messages
Signed-off-by: SizableShrimp <[email protected]>
2022-09-29 22:11:12 -07:00
DBotThePony 515c6082e0 Make ForgeConfigSpec$Builder.comment able to be called multiple times for the same entry. (#9056) 2022-09-27 23:23:59 -07:00
ChampionAsh5357 a753598113 Fix control modifier for mac with KeyMappings using Alt instead of Super (#9057) 2022-09-27 11:15:11 -07:00
J.T. McQuigg bc6c4be4e4 Fix is_desert tag not being applied correctly. (#9051) 2022-09-26 11:08:24 -07:00
Andy Dingley 98823a8f07 Fix mob griefing event for SmallFireballs not using owner entity. (#9038) 2022-09-21 13:24:25 -07:00
David Dempsey ecd8f1e54d Fix minecarts on rails not properly slowing down in water (#9033) 2022-09-21 13:20:03 -07:00
LexManos b0caea8e20 Change codestyle for BookShelves tag. Closes #9027
Add IS_CAVE tag Closes #8885
Add IS_DESERT tag Closes #8979
Simplify Mangrove Swamp tags Closes #8980
2022-09-09 11:27:39 -07:00
nikita488 e0477f8776 Allow faces of an "elements" model to have disabled ambient occlusion (#9019) 2022-09-08 16:17:44 +01:00
bconlon 94e1e54b53 [1.19.x] Recipe ID-based grouping between modded and vanilla recipes. (#8876) 2022-09-08 16:13:07 +01:00
nitro_dynamite18 9ce72331b7 Update fence_gates/wooden (#8936) 2022-09-08 16:12:26 +01:00
Jais Djurhuus-Kempel 1c31f42dae [1.19.x] Added event for growing fungus (#8981) 2022-09-08 16:11:59 +01:00
agnor99 0978a94358 Added Bookshelves block tag (#8991) 2022-09-08 16:11:39 +01:00
GizmoTheMoonPig e956a9c9f3 Create a Forge EntityType Tag for Bosses (#9017) 2022-09-08 16:10:48 +01:00
Monica S 82026d11a4 Allow mods to specify shader import namespace (#9021) 2022-09-08 16:10:31 +01:00
ferriarnus 6d233ac75c Grindstone Events (#8934)
One to modify the output, and one to modify the input.
2022-09-08 15:55:43 +01:00
Reece Mackie 73c1934e7e Fix the serialized names of the enum (#9014) 2022-09-04 19:46:54 +01:00
Technici4n bf1194ec75 Fix tryEmptyContainerAndStow duping fluids with stackable containers (#9004) 2022-09-03 21:48:07 +01:00
Ted Senft 22d2740725 Add mod mismatch event (#8989) 2022-09-03 21:26:43 +01:00
Minecraftschurli 02f26dc7a1 [1.19.x] add methods with more context to tree growers (#8956) 2022-09-03 20:24:00 +01:00
28Pollux28 db14cbb0e0 [1.19.X] Adding more precise events for Advancements (#8360) 2022-09-03 20:17:16 +01:00
Luke BemishandLexManos a2b35cae92 Default IItemHandler capability for shulker box itemstacks (#8827)
Co-authored-by: LexManos <[email protected]>
2022-09-03 20:16:25 +01:00
Take Weiland aab0e4c82e [1.19] Add hook for items to remain in the hotbar when picking blocks/entities (#8872) 2022-09-03 20:12:13 +01:00
Reece Mackieandsciwhiz12 6609708d14 [1.19.x] Block Model Builder Root Transform Support (#8860)
Co-authored-by: sciwhiz12 <[email protected]>
2022-09-03 20:11:46 +01:00
Budschie ed198f062c [1.19.x] Make LivingSetAttackTargetEvent compatible with the Brain/Behavior system. (Port of PR #8918) (#8954) 2022-09-03 20:11:10 +01:00
thedarkcolour 4e2d656e9d [1.19.x] Add IForgeBlock#onTreeGrow to replace IForgeBlock#onPlantGrow from 1.16 (#8999) 2022-09-03 20:07:09 +01:00
bconlon 2a4230868f [1.19.x] Moved Player.resetAttackStrengthTicker() to the end of Player.attack() (#9000) 2022-09-03 20:06:35 +01:00
Sirttas cf778b1759 fix misplaced patch in sapling block (#9005) 2022-09-03 20:05:37 +01:00
Brennan Ward 1b6daddd40 Fix failed entity interactions consuming the click. (#9007) 2022-09-03 20:00:57 +01:00
sciwhiz12 d7b137d144 Fix entity selector permission check to check original source (#8995)
Permission checks should be against the command source and not the
target entity, as is done in vanilla.

Fixes #8994
2022-08-25 11:42:11 -07:00
한현빈 b5d5855559 Hotfix for 1.19.2 item animation bug (#8987)
* [HOT FIX]: Fixes #8985 by no-oping for vanilla models instead of throwing error

Signed-off-by: tmvkrpxl0 <[email protected]>
2022-08-20 11:38:24 +02:00
LexManos c0aa8dd808 Add ability to Auto register capabilities via annotation (#8972) 2022-08-17 15:06:35 -07:00
198 changed files with 4729 additions and 573 deletions

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
name: 'Spam label'
on:
issues:
types: [labeled]
pull_request:
types: [labeled]
discussion:
types: [labeled]
permissions:
contents: read
issues: write
pull-requests: write
discussions: write
jobs:
lock:
if: ${{ (github.event.label.name == 'spam') && (github.event.action == 'labeled') }}
runs-on: ubuntu-latest
steps:
- uses: peter-evans/close-issue@v2
name: Close Issue
with:
close-reason: 'not_planned'
if: ${{ github.event_name != 'pull_request' }}
- run: gh pr close ${{ github.event.pull_request.html_url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Close PR
if: ${{ github.event_name == 'pull_request' }}
- uses: maxkomarychev/[email protected]
name: Lock PR
if: ${{ github.event_name == 'pull_request' }}
with:
token: "${{ secrets.GITHUB_TOKEN }}"
issue_number: ${{ github.event.number }}
- uses: OSDKDev/[email protected]
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
name: Lock issue
if: ${{ github.event_name != 'pull_request' }}
+73 -1
View File
@@ -1,5 +1,7 @@
import jetbrains.buildServer.configs.kotlin.v2019_2.*
import jetbrains.buildServer.configs.kotlin.v2019_2.projectFeatures.githubIssues
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
/*
The settings script is an entry point for defining a TeamCity
@@ -30,11 +32,13 @@ project {
buildType(Build)
buildType(BuildSecondaryBranches)
buildType(PullRequests)
buildType(PullRequestChecks)
buildType(PullRequestCompatibility)
params {
text("docker_jdk_version", "17", label = "Gradle version", description = "The version of the JDK to use during execution of tasks in a JDK.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("docker_gradle_version", "7.4", label = "Gradle version", description = "The version of Gradle to use during execution of Gradle tasks.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("git_main_branch", "1.18.x", label = "Git Main Branch", description = "The git main or default branch to use in VCS operations.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("git_main_branch", "1.19.x", label = "Git Main Branch", description = "The git main or default branch to use in VCS operations.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
text("git_branch_spec", """
+:refs/heads/(main*)
+:refs/heads/(master*)
@@ -134,3 +138,71 @@ object PullRequests : BuildType({
""".trimIndent()
}
})
object PullRequestChecks : BuildType({
templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"))
id("MinecraftForge_MinecraftForge__PullRequestChecks")
name = "Pull Requests (Checks)"
description = "Checks pull requests for the project"
steps {
gradle {
name = "Check"
id = "RUNNER_10_Check"
tasks = "checkAll"
gradleParams = "--continue %gradle_custom_args%"
enableStacktrace = true
dockerImage = "%docker_gradle_image%"
dockerRunParameters = """
-v "/opt/cache/agent/gradle:/home/gradle/.gradle"
-v "/opt/cache/shared/gradle:/home/gradle/rocache:ro"
--network=host
-u 1000:1000
%docker_additional_args%
""".trimIndent()
}
}
vcs {
branchFilter = """
+:*
-:1.*
-:<default>
""".trimIndent()
}
})
object PullRequestCompatibility : BuildType({
templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"))
id("MinecraftForge_MinecraftForge__PullRequestCompatibility")
name = "Pull Requests (Compatibility)"
description = "Validates binary compatibility for pull requests made to the project"
steps {
gradle {
name = "Validate"
id = "RUNNER_10_Compatibility"
tasks = "checkJarCompatibility"
gradleParams = "--continue %gradle_custom_args%"
enableStacktrace = true
dockerImage = "%docker_gradle_image%"
dockerRunParameters = """
-v "/opt/cache/agent/gradle:/home/gradle/.gradle"
-v "/opt/cache/shared/gradle:/home/gradle/rocache:ro"
--network=host
-u 1000:1000
%docker_additional_args%
""".trimIndent()
}
}
vcs {
branchFilter = """
+:*
-:1.*
-:<default>
""".trimIndent()
}
})
+30 -38
View File
@@ -19,7 +19,7 @@ plugins {
id 'com.github.ben-manes.versions' version '0.36.0'
id 'net.minecraftforge.gradleutils' version '2.+'
id 'eclipse'
id 'de.undercouch.download' version '4.1.2'
id 'de.undercouch.download' version '5.1.3'
id 'net.minecraftforge.gradle.patcher' version '[5.1.50,5.2.0)' apply false
id 'net.minecraftforge.gradle.mcp' version '[5.1.50,5.2.0)' apply false
}
@@ -77,7 +77,7 @@ ext {
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.3.0'
JAR_SPLITTER = 'net.minecraftforge:jarsplitter:1.1.4'
FART = 'net.minecraftforge:ForgeAutoRenamingTool:0.1.22:all'
MIN_TAG_FOR_CHANGELOG = "41.0"
MIN_TAG_FOR_CHANGELOG = '41.0'
}
println('Version: ' + VERSION +
@@ -1184,8 +1184,6 @@ project(':forge') {
excs.from patcher.excs
}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs, findFieldInstanceChecks]){}
task checkPatchesAndFix(type: CheckPatches, dependsOn: genPatches) {
patchDir = file("$rootDir/patches")
autoFix = true
@@ -1202,57 +1200,51 @@ project(':forge') {
lineEnding = '\n'
}
def baseForgeVersion = System.getProperty("forge.compatibility_check_version")
if (baseForgeVersion == null)
baseForgeVersion = "${MC_VERSION}-${GIT_INFO.tag}.0"
if (baseForgeVersion == "null")
baseForgeVersion = null // Allow disabling from system property if not wanted
def baseForgeUniversal = null
if (baseForgeVersion != null)
baseForgeUniversal = project.dependencies.create("net.minecraftforge:forge:${baseForgeVersion}:universal")
def baseForgeVersionProperty = project.objects.property(String)
baseForgeVersionProperty.set(project.provider { getLatestForgeVersion(MC_VERSION) }.map { MC_VERSION + '-' + it })
baseForgeVersionProperty.finalizeValueOnRead()
def jarCompatibilityTaskSetup = { task ->
task.group = 'jar compatibility'
task.onlyIf {
baseForgeVersion != null
baseForgeVersionProperty.getOrNull() != null
}
task.inputs.property 'baseForgeVersion', baseForgeVersion
}
task downloadBaseCompatibilityBinPatches(type: DownloadBaseCompatibilityBinPatches) {
inputVersion = baseForgeVersion
tasks.register('setupCheckJarCompatibility', SetupCheckJarCompatibility) {
inputVersion = baseForgeVersionProperty
}
task applyBaseCompatibilityJarBinPatches(type: ApplyBinPatches) {
tasks.register('applyBaseCompatibilityJarBinPatches', ApplyBinPatches) {
jarCompatibilityTaskSetup(it)
clean = createJoinedSRG.output
patch = downloadBaseCompatibilityBinPatches.output
clean = project.tasks.createJoinedSRG.output
patch = project.tasks.named('setupCheckJarCompatibility').flatMap { it.baseBinPatchesOutput }
output = project.layout.buildDirectory.dir(name).map { it.file('output.jar') }
}
task checkJarCompatibility(type: CheckJarCompatibility) {
tasks.register('mergeBaseForgeJar', MergeJars) {
jarCompatibilityTaskSetup(it)
if (baseForgeVersion != null) {
def fmlLibs = project.configurations.detachedConfiguration(PACKED_DEPS.collect {
def artifactId = it.split(':')[1]
return project.dependencies.create("net.minecraftforge:${artifactId}:${baseForgeVersion}")
}.toArray(Dependency[]::new))
baseJar = project.tasks.applyBaseCompatibilityJarBinPatches.output
baseLibraries.from(project.configurations.detachedConfiguration(baseForgeUniversal))
baseLibraries.from(project.tasks.createJoinedSRG.output)
baseLibraries.from(fmlLibs)
inputJar = project.tasks.reobfJar.output
concreteLibraries.from(PACKED_DEPS.collect { rootProject.tasks.getByPath(it).archiveFile })
commonLibraries.from(project.configurations.minecraftImplementation)
commonLibraries.from(project.configurations.installer)
commonLibraries.from(project.configurations.moduleonly)
}
inputJars.from(project.tasks.named('applyBaseCompatibilityJarBinPatches').flatMap { it.output })
inputJars.from(baseForgeVersionProperty.map { inputVersion ->
def output = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-universal.jar") }.get().asFile
project.rootProject.extensions.download.run {
src "https://maven.minecraftforge.net/net/minecraftforge/forge/${inputVersion}/forge-${inputVersion}-universal.jar"
dest output
}
return output
})
}
tasks.register('checkJarCompatibility', CheckJarCompatibility) {
jarCompatibilityTaskSetup(it)
dependsOn 'setupCheckJarCompatibility'
baseJar = project.tasks.named('mergeBaseForgeJar').flatMap { it.output }
}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs, findFieldInstanceChecks, checkPatches, checkLicenses]){}
task launcherJson(type: LauncherJson) {
packedDependencies = [':fmlloader:jar']
doFirst {
+1
View File
@@ -7,4 +7,5 @@ dependencies {
implementation 'org.ow2.asm:asm:9.3'
implementation 'org.ow2.asm:asm-tree:9.3'
implementation 'net.minecraftforge:srgutils:0.4.+'
implementation 'commons-io:commons-io:2.8.0'
}
@@ -1,39 +0,0 @@
package net.minecraftforge.forge.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.nio.file.Files
abstract class DownloadBaseCompatibilityBinPatches extends DefaultTask {
DownloadBaseCompatibilityBinPatches() {
group = 'jar compatibility'
onlyIf {
inputVersion.getOrNull() != null
}
output.convention(project.layout.buildDirectory.dir(name).map { it.file('joined.lzma') })
}
@TaskAction
void run() {
def dep = project.dependencies.create("net.minecraftforge:forge:${inputVersion.get()}:userdev")
def baseForgeUserdev = project.configurations.detachedConfiguration(dep).resolve().iterator().next()
def joinedLzma = project.zipTree(baseForgeUserdev).matching { it.include('joined.lzma') }.singleFile
Files.copy(joinedLzma.toPath(), output.get().asFile.toPath())
}
@Input
@Optional
abstract Property<String> getInputVersion()
@OutputFile
abstract RegularFileProperty getOutput()
}
@@ -0,0 +1,44 @@
package net.minecraftforge.forge.tasks
import org.apache.commons.io.IOUtils
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
abstract class MergeJars extends DefaultTask {
MergeJars() {
output.convention(project.layout.buildDirectory.dir(name).map { it.file('output.jar') })
}
@TaskAction
void run() {
def jars = inputJars.files
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(output.get().asFile))) {
for (def jar : jars) {
try (ZipInputStream zin = new ZipInputStream(new FileInputStream(jar))) {
def entry
while ((entry = zin.getNextEntry()) != null) {
ZipEntry _new = new ZipEntry(entry.getName())
_new.setTime(0) //SHOULD be the same time as the main entry, but NOOOO _new.setTime(entry.getTime()) throws DateTimeException, so you get 0, screw you!
zout.putNextEntry(_new)
IOUtils.copy(zin, zout)
}
}
}
}
}
@InputFiles
abstract ConfigurableFileCollection getInputJars()
@OutputFile
abstract RegularFileProperty getOutput()
}
@@ -0,0 +1,64 @@
package net.minecraftforge.forge.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Dependency
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.nio.file.Files
import java.nio.file.StandardCopyOption
abstract class SetupCheckJarCompatibility extends DefaultTask {
SetupCheckJarCompatibility() {
group = 'jar compatibility'
onlyIf {
inputVersion.getOrNull() != null
}
baseBinPatchesOutput.convention(project.layout.buildDirectory.dir(name).map { it.file('joined.lzma') })
}
@TaskAction
void run() {
def inputVersion = inputVersion.get()
def fmlLibs = project.configurations.detachedConfiguration(project.PACKED_DEPS.collect {
def artifactId = it.split(':')[1]
return project.dependencies.create("net.minecraftforge:${artifactId}:${inputVersion}")
}.toArray(Dependency[]::new))
project.tasks.named('checkJarCompatibility') {
baseLibraries.from(project.tasks.createJoinedSRG.output)
baseLibraries.from(project.provider {
fmlLibs.resolvedConfiguration.lenientConfiguration.files
})
inputJar = project.tasks.reobfJar.output
concreteLibraries.from(project.PACKED_DEPS.collect { project.rootProject.tasks.getByPath(it).archiveFile })
commonLibraries.from(project.configurations.minecraftImplementation)
commonLibraries.from(project.configurations.installer)
commonLibraries.from(project.configurations.moduleonly)
}
def baseForgeUserdev = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-userdev.jar") }.get().asFile
project.rootProject.extensions.download.run {
src "https://maven.minecraftforge.net/net/minecraftforge/forge/${inputVersion}/forge-${inputVersion}-userdev.jar"
dest baseForgeUserdev
}
def joinedLzma = project.zipTree(baseForgeUserdev).matching { it.include('joined.lzma') }.singleFile
Files.copy(joinedLzma.toPath(), baseBinPatchesOutput.get().asFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
@Input
@Optional
abstract Property<String> getInputVersion()
@OutputFile
abstract RegularFileProperty getBaseBinPatchesOutput()
}
@@ -18,17 +18,17 @@ public class Util {
return md.digest().collect {String.format "%02x", it}.join()
}
File.metaClass.getSha1 = { !delegate.exists() ? null : delegate.sha1() }
File.metaClass.json = { -> new JsonSlurper().parseText(delegate.text) }
File.metaClass.getJson = { return delegate.exists() ? new JsonSlurper().parse(delegate) : [:] }
File.metaClass.setJson = { json -> delegate.text = new JsonBuilder(json).toPrettyString() }
Date.metaClass.iso8601 = { ->
def format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
def result = format.format(delegate)
return result[0..21] + ':' + result[22..-1]
}
String.metaClass.rsplit = { String del, int limit = -1 ->
def lst = new ArrayList()
def x = 0, idx
@@ -41,7 +41,7 @@ public class Util {
return lst
}
}
public static String[] getClasspath(project, libs, artifact) {
def ret = []
artifactTree(project, artifact).each { key, lib ->
@@ -51,7 +51,7 @@ public class Util {
}
return ret
}
public static def getArtifacts(project, config, classifiers) {
def ret = [:]
config.resolvedConfiguration.resolvedArtifacts.each {
@@ -75,7 +75,7 @@ public class Util {
url = "https://maven.minecraftforge.net/${path}"
}
//TODO remove when Mojang launcher is updated
if (!classifiers && art.classifier != null) {
if (!classifiers && art.classifier != null) {
//Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
// However, keep the path normal so that our mirror system works.
art.version = "${art.version}-${art.classifier}"
@@ -96,14 +96,14 @@ public class Util {
}
return ret
}
public static def getMavenPath(task) {
public static def getMavenPath(task) {
def classifier = task.archiveClassifier.get()
def dep = "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
return "${task.project.group.replace('.', '/')}/${task.project.name}/${task.project.version}/${task.project.name}-${task.project.version}".toString() + (classifier == '' ? '' : '-' + classifier) + '.jar'
}
public static def getMavenDep(task) {
public static def getMavenDep(task) {
def classifier = task.archiveClassifier.get()
return "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
}
@@ -127,7 +127,7 @@ public class Util {
def files = cfg.resolve()
return getArtifacts(project, cfg, true)
}
private static boolean checkExists(url) {
try {
def code = new URL(url).openConnection().with {
@@ -142,4 +142,9 @@ public class Util {
throw e
}
}
public static String getLatestForgeVersion(mcVersion) {
def json = new JsonSlurper().parseText(new URL("https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json").getText("UTF-8"))
return json.promos["$mcVersion-latest"]
}
}
@@ -5,13 +5,18 @@
package net.minecraftforge.fml;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.config.IConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.loading.FMLLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.Supplier;
public class ModLoadingContext
{
private static final Logger LOGGER = LogUtils.getLogger();
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
private Object languageExtension;
private ModLoadingStage stage;
@@ -46,10 +51,24 @@ public class ModLoadingContext
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getActiveContainer().getModId());
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec, String fileName) {
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getActiveContainer().getModId(), fileName);
return;
}
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
}
@@ -8,6 +8,7 @@ package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
@@ -53,4 +54,16 @@ public class FileUtils
return "";
}
}
public static boolean matchFileName(String path, String... matches) {
// Extract file name from path
String name = path.substring(Math.min(path.lastIndexOf(File.separatorChar) + 1, path.length()));
// Check if it contains any of the desired keywords
for (String match : matches) {
if (name.contains(match)) {
return true;
}
}
return false;
}
}
@@ -6,21 +6,27 @@
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import cpw.mods.modlauncher.api.NamedPath;
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleDescriptor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;
import java.util.Set;
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Set<String> SERVICES = Set.of(
"cpw.mods.modlauncher.api.ITransformationService",
"net.minecraftforge.forgespi.locating.IModLocator",
"net.minecraftforge.forgespi.locating.IDependencyLocator"
);
@Override
public List<NamedPath> candidates(final Path gameDirectory) {
@@ -51,14 +57,11 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
if (!Files.isRegularFile(path)) return;
if (!path.toString().endsWith(".jar")) return;
if (LamdbaExceptionUtils.uncheck(() -> Files.size(path)) == 0) return;
try (ZipFile zf = new ZipFile(new File(path.toUri()))) {
if (zf.getEntry("META-INF/services/cpw.mods.modlauncher.api.ITransformationService") != null) {
found.add(new NamedPath(zf.getName(), path));
} else if (zf.getEntry("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator") != null) {
found.add(new NamedPath(zf.getName(), path));
}
} catch (IOException ioe) {
LOGGER.error("Zip Error when loading jar file {}", path, ioe);
}
SecureJar jar = SecureJar.from(path);
jar.moduleDataProvider().descriptor().provides().stream()
.map(ModuleDescriptor.Provides::service)
.filter(SERVICES::contains)
.forEach(s -> found.add(new NamedPath(s, path)));
}
}
@@ -210,10 +210,24 @@ public class ModSorter
if (!missingVersions.isEmpty()) {
if (mandatoryMissing > 0) {
LOGGER.error(LOADING, "Missing mandatory dependencies: {}", missingVersions.stream().filter(IModInfo.ModVersion::isMandatory).map(IModInfo.ModVersion::getModId).collect(Collectors.joining(", ")));
LOGGER.error(
LOADING,
"Missing or unsupported mandatory dependencies:\n{}",
missingVersions.stream()
.filter(IModInfo.ModVersion::isMandatory)
.map(ver -> formatDependencyError(ver, modVersions))
.collect(Collectors.joining("\n"))
);
}
if (missingVersions.size() - mandatoryMissing > 0) {
LOGGER.error(LOADING, "Unsupported installed optional dependencies: {}", missingVersions.stream().filter(ver -> !ver.isMandatory()).map(IModInfo.ModVersion::getModId).collect(Collectors.joining(", ")));
LOGGER.error(
LOADING,
"Unsupported installed optional dependencies:\n{}",
missingVersions.stream()
.filter(ver -> !ver.isMandatory())
.map(ver -> formatDependencyError(ver, modVersions))
.collect(Collectors.joining("\n"))
);
}
return missingVersions.stream()
@@ -225,6 +239,18 @@ public class ModSorter
return Collections.emptyList();
}
private static String formatDependencyError(IModInfo.ModVersion dependency, Map<String, ArtifactVersion> modVersions)
{
ArtifactVersion installed = modVersions.get(dependency.getModId());
return String.format(
"\tMod ID: '%s', Requested by: '%s', Expected range: '%s', Actual version: '%s'",
dependency.getModId(),
dependency.getOwner().getModId(),
dependency.getVersionRange(),
installed != null ? installed.toString() : "[MISSING]"
);
}
private boolean modVersionNotContained(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
{
return !(VersionSupportMatrix.testVersionSupportMatrix(mv.getVersionRange(), mv.getModId(), "mod", (modId, range) -> modVersions.containsKey(modId) &&
@@ -6,6 +6,7 @@
package net.minecraftforge.fml.loading.targets;
import cpw.mods.jarhandling.SecureJar;
import net.minecraftforge.fml.loading.FileUtils;
import java.io.File;
import java.nio.file.Path;
@@ -29,7 +30,7 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
// The extra jar is on the classpath, so try and pull it out of the legacy classpath
var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find client-extra").split(File.pathSeparator);
var extra = Paths.get(Arrays.stream(legacyCP).filter(e -> e.contains("client-extra")).findFirst().orElseThrow(() -> new IllegalStateException("Could not find client-extra in legacy classpath")));
var extra = findJarOnClasspath(legacyCP, "client-extra");
mcstream.add(extra);
// The MC code/Patcher edits are in exploded directories
@@ -77,11 +78,18 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
protected List<Path> getFmlStuff(String[] classpath) {
// We also want the FML things, fmlcore, javafmllanguage, mclanguage, I don't like hard coding these, but hey whatever works for now.
return Arrays.stream(classpath)
.filter(e -> e.contains("fmlcore") || e.contains("javafmllanguage") || e.contains("lowcodelanguage") || e.contains("mclanguage"))
.filter(e -> FileUtils.matchFileName(e, "fmlcore", "javafmllanguage", "lowcodelanguage", "mclanguage"))
.map(Paths::get)
.toList();
}
protected static Path findJarOnClasspath(String[] classpath, String match) {
return Paths.get(Arrays.stream(classpath)
.filter(e -> FileUtils.matchFileName(e, match))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Could not find " + match + " in classpath")));
}
protected BiPredicate<String, String> getMcFilter(Path extra, List<Path> minecraft, Stream.Builder<List<Path>> mods) {
final var packages = getPackages();
final var extraPath = extra.toString().replace('\\', '/');
@@ -10,8 +10,6 @@ import net.minecraftforge.fml.loading.VersionInfo;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -41,8 +39,4 @@ public abstract class CommonUserdevLaunchHandler extends CommonDevLaunchHandler
}
protected abstract void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods);
protected static Path findJarOnClasspath(String[] classpath, String match) {
return Paths.get(Arrays.stream(classpath).filter(e -> e.contains(match)).findFirst().orElseThrow(() -> new IllegalStateException("Could not find " + match + " in classpath")));
}
}
+1
View File
@@ -13,6 +13,7 @@
<MarkerFilter marker="REGISTRIES" onMatch="${sys:forge.logging.marker.registries:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="REGISTRYDUMP" onMatch="${sys:forge.logging.marker.registrydump:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="SPLASH" onMatch="${sys:forge.logging.marker.splash:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="RESOURCE-CACHE" onMatch="${sys:forge.logging.marker.resource.cache:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="FORGEMOD" onMatch="${sys:forge.logging.marker.forgemod:-ACCEPT}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="LOADING" onMatch="${sys:forge.logging.marker.loading:-ACCEPT}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="CORE" onMatch="${sys:forge.logging.marker.core:-ACCEPT}" onMismatch="NEUTRAL"/>
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
@@ -51,7 +51,7 @@ public class LowCodeModLanguageProvider implements IModLanguageProvider
throw new ModLoadingException(info, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmodclass", e);
}
} catch (NoSuchMethodException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
LOGGER.fatal(LOADING, "Unable to load FMLModContainer, wut?", e);
LOGGER.fatal(LOADING, "Unable to load LowCodeModContainer, wut?", e);
final Class<RuntimeException> mle = (Class<RuntimeException>) LamdbaExceptionUtils.uncheck(() -> Class.forName("net.minecraftforge.fml.ModLoadingException", true, Thread.currentThread().getContextClassLoader()));
final Class<ModLoadingStage> mls = (Class<ModLoadingStage>) LamdbaExceptionUtils.uncheck(() -> Class.forName("net.minecraftforge.fml.ModLoadingStage", true, Thread.currentThread().getContextClassLoader()));
throw LamdbaExceptionUtils.uncheck(() -> LamdbaExceptionUtils.uncheck(() -> mle.getConstructor(IModInfo.class, mls, String.class, Throwable.class)).newInstance(info, Enum.valueOf(mls, "CONSTRUCT"), "fml.modloading.failedtoloadmodclass", e));
@@ -9,6 +9,7 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.Material;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -75,7 +76,7 @@ public class ExampleMod
}
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class ClientModEvents
{
@SubscribeEvent
@@ -0,0 +1,11 @@
--- a/com/mojang/blaze3d/vertex/PoseStack.java
+++ b/com/mojang/blaze3d/vertex/PoseStack.java
@@ -11,7 +_,7 @@
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
-public class PoseStack {
+public class PoseStack implements net.minecraftforge.client.extensions.IForgePoseStack {
private final Deque<PoseStack.Pose> f_85834_ = Util.m_137469_(Queues.newArrayDeque(), (p_85848_) -> {
Matrix4f matrix4f = new Matrix4f();
matrix4f.m_27624_();
@@ -21,3 +21,13 @@
if (SharedConstants.f_136183_) {
throw illegalargumentexception;
}
@@ -692,7 +_,8 @@
public static <T, R> Function<T, R> m_143827_(final Function<T, R> p_143828_) {
return new Function<T, R>() {
- private final Map<T, R> f_211548_ = Maps.newHashMap();
+ // FORGE: Allow using memoized functions from multiple threads.
+ private final Map<T, R> f_211548_ = Maps.newConcurrentMap();
public R apply(T p_214691_) {
return this.f_211548_.computeIfAbsent(p_214691_, p_143828_);
@@ -1,5 +1,14 @@
--- a/net/minecraft/client/ClientRecipeBook.java
+++ b/net/minecraft/client/ClientRecipeBook.java
@@ -51,7 +_,7 @@
for(Recipe<?> recipe : p_90643_) {
if (!recipe.m_5598_() && !recipe.m_142505_()) {
RecipeBookCategories recipebookcategories = m_90646_(recipe);
- String s = recipe.m_6076_();
+ String s = recipe.m_6076_().isEmpty() ? recipe.m_6423_().toString() : recipe.m_6076_(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
if (s.isEmpty()) {
map.computeIfAbsent(recipebookcategories, (p_90645_) -> {
return Lists.newArrayList();
@@ -103,6 +_,8 @@
} else if (recipetype == RecipeType.f_44113_) {
return RecipeBookCategories.SMITHING;
@@ -302,7 +302,7 @@
return;
}
+ if(!this.f_91074_.canInteractWith(entityhitresult.m_82443_(), 0)) return; //Forge: Entity may be traced via attack range, but the player may not have sufficient reach. No padding in client code.
+ if(!this.f_91074_.canInteractWith(entityhitresult.m_82443_(), 0)) break; //Forge: Entity may be traced via attack range, but the player may not have sufficient reach. No padding in client code.
InteractionResult interactionresult = this.f_91072_.m_105230_(this.f_91074_, entity, entityhitresult, interactionhand);
if (!interactionresult.m_19077_()) {
interactionresult = this.f_91072_.m_105226_(this.f_91074_, entity, interactionhand);
@@ -27,7 +27,7 @@
EMPTY(false),
ITEM(false),
BLOCK(false),
@@ -411,10 +_,30 @@
@@ -411,10 +_,29 @@
private ArmPose(boolean p_102896_) {
this.f_102890_ = p_102896_;
@@ -52,8 +52,7 @@
+ }
+
+ public <T extends LivingEntity> void applyTransform(HumanoidModel<T> model, T entity, net.minecraft.world.entity.HumanoidArm arm) {
+ com.google.common.base.Preconditions.checkNotNull(this.forgeArmPose, "applyTransform() must not be called on a vanilla ArmPose!");
+ this.forgeArmPose.applyTransform(model, entity, arm);
+ if (this.forgeArmPose != null) this.forgeArmPose.applyTransform(model, entity, arm);
+ }
+ // FORGE END
}
@@ -19,3 +19,14 @@
this.m_241119_(p_242290_, component);
}
}
@@ -194,7 +_,9 @@
}
boolean m_241171_(ChatType.Bound p_241518_, PlayerChatMessage p_241542_, Component p_241510_) {
- this.f_240348_.f_91065_.m_93076_().m_93785_(p_241510_);
+ Component forgeComponent = net.minecraftforge.client.ForgeHooksClient.onClientChat(p_241518_, p_241510_, p_241542_, p_241542_.m_241067_());
+ if (forgeComponent == null) return false;
+ this.f_240348_.f_91065_.m_93076_().m_93785_(forgeComponent);
this.m_241119_(p_241518_, p_241542_.m_237220_());
this.m_240498_(p_241510_, p_241542_.m_241109_());
this.f_240659_ = Util.m_137550_();
@@ -0,0 +1,11 @@
--- a/net/minecraft/client/multiplayer/resolver/AddressCheck.java
+++ b/net/minecraft/client/multiplayer/resolver/AddressCheck.java
@@ -16,7 +_,7 @@
boolean m_142408_(ServerAddress p_171830_);
static AddressCheck m_171828_() {
- final ImmutableList<Predicate<String>> immutablelist = Streams.stream(ServiceLoader.load(BlockListSupplier.class)).map(BlockListSupplier::createBlockList).filter(Objects::nonNull).collect(ImmutableList.toImmutableList());
+ final ImmutableList<Predicate<String>> immutablelist = Streams.stream(ServiceLoader.load(BlockListSupplier.class, net.minecraftforge.fml.loading.FMLLoader.class.getClassLoader())).map(BlockListSupplier::createBlockList).filter(Objects::nonNull).collect(ImmutableList.toImmutableList());
return new AddressCheck() {
public boolean m_142649_(ResolvedServerAddress p_171835_) {
String s = p_171835_.m_142727_();
@@ -109,7 +109,7 @@
+ BLOCK_RENDER_TYPES.put(net.minecraftforge.registries.ForgeRegistries.BLOCKS.getDelegateOrThrow(block), layers);
+ }
+
+ public static void setRenderLayer(Fluid fluid, RenderType type) {
+ public static synchronized void setRenderLayer(Fluid fluid, RenderType type) {
+ com.google.common.base.Preconditions.checkArgument(type.getChunkLayerId() >= 0, "The argument must be a valid chunk render type returned by RenderType#chunkBufferLayers().");
+ checkClientLoading();
+ FLUID_RENDER_TYPES.put(net.minecraftforge.registries.ForgeRegistries.FLUIDS.getDelegateOrThrow(fluid), type);
@@ -30,3 +30,28 @@
InputStream inputstream = resource.m_215507_();
try {
@@ -232,11 +_,11 @@
private final Set<String> f_173369_ = Sets.newHashSet();
public String m_142138_(boolean p_173374_, String p_173375_) {
- p_173375_ = FileUtil.m_179924_((p_173374_ ? s1 : "shaders/include/") + p_173375_);
- if (!this.f_173369_.add(p_173375_)) {
+ // FORGE: use the mod's namespace to look up resources if specified
+ ResourceLocation resourcelocation = net.minecraftforge.client.ForgeHooksClient.getShaderImportLocation(s1, p_173374_, p_173375_);
+ if (!this.f_173369_.add(resourcelocation.toString())) {
return null;
} else {
- ResourceLocation resourcelocation = new ResourceLocation(p_173375_);
try {
Reader reader = p_173341_.m_215597_(resourcelocation);
@@ -262,7 +_,8 @@
return s2;
} catch (IOException ioexception) {
- ShaderInstance.f_173323_.error("Could not open GLSL import {}: {}", p_173375_, ioexception.getMessage());
+ // FORGE: specify the namespace of the failed import in case of duplicates from multiple mods
+ ShaderInstance.f_173323_.error("Could not open GLSL import {}: {}", resourcelocation, ioexception.getMessage());
return "#error " + ioexception.getMessage();
}
}
@@ -9,7 +9,7 @@
this.f_110901_ = new LiquidBlockRenderer();
}
@@ -45,19 +_,27 @@
@@ -45,19 +_,30 @@
return this.f_110899_;
}
@@ -31,11 +31,14 @@
+ renderBatched(p_234356_, p_234357_, p_234358_, p_234359_, p_234360_, p_234361_, p_234362_, net.minecraftforge.client.model.data.ModelData.EMPTY, null);
+ }
+ public void renderBatched(BlockState p_234356_, BlockPos p_234357_, BlockAndTintGetter p_234358_, PoseStack p_234359_, VertexConsumer p_234360_, boolean p_234361_, RandomSource p_234362_, net.minecraftforge.client.model.data.ModelData modelData, net.minecraft.client.renderer.RenderType renderType) {
+ renderBatched(p_234356_, p_234357_, p_234358_, p_234359_, p_234360_, p_234361_, p_234362_, modelData, renderType, true);
+ }
+ public void renderBatched(BlockState p_234356_, BlockPos p_234357_, BlockAndTintGetter p_234358_, PoseStack p_234359_, VertexConsumer p_234360_, boolean p_234361_, RandomSource p_234362_, net.minecraftforge.client.model.data.ModelData modelData, net.minecraft.client.renderer.RenderType renderType, boolean queryModelSpecificData) { // TODO 1.20: Move to the signature above
try {
RenderShape rendershape = p_234356_.m_60799_();
if (rendershape == RenderShape.MODEL) {
- this.f_110900_.m_234379_(p_234358_, this.m_110910_(p_234356_), p_234356_, p_234357_, p_234359_, p_234360_, p_234361_, p_234362_, p_234356_.m_60726_(p_234357_), OverlayTexture.f_118083_);
+ this.f_110900_.tesselateBlock(p_234358_, this.m_110910_(p_234356_), p_234356_, p_234357_, p_234359_, p_234360_, p_234361_, p_234362_, p_234356_.m_60726_(p_234357_), OverlayTexture.f_118083_, modelData, renderType);
+ this.f_110900_.tesselateBlock(p_234358_, this.m_110910_(p_234356_), p_234356_, p_234357_, p_234359_, p_234360_, p_234361_, p_234362_, p_234356_.m_60726_(p_234357_), OverlayTexture.f_118083_, modelData, renderType, queryModelSpecificData); // TODO 1.20: Remove last argument
}
} catch (Throwable throwable) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/renderer/block/ModelBlockRenderer.java
+++ b/net/minecraft/client/renderer/block/ModelBlockRenderer.java
@@ -40,72 +_,85 @@
@@ -40,72 +_,88 @@
this.f_110995_ = p_110999_;
}
@@ -12,10 +12,13 @@
+ tesselateBlock(p_234380_, p_234381_, p_234382_, p_234383_, p_234384_, p_234385_, p_234386_, p_234387_, p_234388_, p_234389_, net.minecraftforge.client.model.data.ModelData.EMPTY, null);
+ }
+ public void tesselateBlock(BlockAndTintGetter p_111048_, BakedModel p_111049_, BlockState p_111050_, BlockPos p_111051_, PoseStack p_111052_, VertexConsumer p_111053_, boolean p_111054_, RandomSource p_111055_, long p_111056_, int p_111057_, net.minecraftforge.client.model.data.ModelData modelData, net.minecraft.client.renderer.RenderType renderType) {
+ tesselateBlock(p_111048_, p_111049_, p_111050_, p_111051_, p_111052_, p_111053_, p_111054_, p_111055_, p_111056_, p_111057_, modelData, renderType, true);
+ }
+ public void tesselateBlock(BlockAndTintGetter p_111048_, BakedModel p_111049_, BlockState p_111050_, BlockPos p_111051_, PoseStack p_111052_, VertexConsumer p_111053_, boolean p_111054_, RandomSource p_111055_, long p_111056_, int p_111057_, net.minecraftforge.client.model.data.ModelData modelData, net.minecraft.client.renderer.RenderType renderType, boolean queryModelSpecificData) { // TODO 1.20: Move to the signature above
+ boolean flag = Minecraft.m_91086_() && p_111050_.getLightEmission(p_111048_, p_111051_) == 0 && p_111049_.useAmbientOcclusion(p_111050_, renderType);
+ Vec3 vec3 = p_111050_.m_60824_(p_111048_, p_111051_);
+ p_111052_.m_85837_(vec3.f_82479_, vec3.f_82480_, vec3.f_82481_);
+ modelData = p_111049_.getModelData(p_111048_, p_111051_, p_111050_, modelData);
+ if (queryModelSpecificData) modelData = p_111049_.getModelData(p_111048_, p_111051_, p_111050_, modelData); // TODO 1.20: Remove this line entirely
try {
if (flag) {
@@ -111,6 +114,14 @@
}
}
@@ -113,6 +_,7 @@
private void m_111012_(BlockAndTintGetter p_111013_, BlockState p_111014_, BlockPos p_111015_, PoseStack p_111016_, VertexConsumer p_111017_, List<BakedQuad> p_111018_, float[] p_111019_, BitSet p_111020_, ModelBlockRenderer.AmbientOcclusionFace p_111021_, int p_111022_) {
for(BakedQuad bakedquad : p_111018_) {
this.m_111039_(p_111013_, p_111014_, p_111015_, bakedquad.m_111303_(), bakedquad.m_111306_(), p_111019_, p_111020_);
+ if (!net.minecraftforge.client.ForgeHooksClient.calculateFaceWithoutAO(p_111013_, p_111014_, p_111015_, bakedquad, p_111020_.get(0), p_111021_.f_111149_, p_111021_.f_111150_))
p_111021_.m_111167_(p_111013_, p_111014_, p_111015_, bakedquad.m_111306_(), p_111019_, p_111020_, bakedquad.m_111307_());
this.m_111023_(p_111013_, p_111014_, p_111015_, p_111017_, p_111016_.m_85850_(), bakedquad, p_111021_.f_111149_[0], p_111021_.f_111149_[1], p_111021_.f_111149_[2], p_111021_.f_111149_[3], p_111021_.f_111150_[0], p_111021_.f_111150_[1], p_111021_.f_111150_[2], p_111021_.f_111150_[3], p_111022_);
}
@@ -217,17 +_,21 @@
}
@@ -0,0 +1,32 @@
--- a/net/minecraft/client/renderer/block/model/BakedQuad.java
+++ b/net/minecraft/client/renderer/block/model/BakedQuad.java
@@ -12,13 +_,19 @@
protected final Direction f_111294_;
protected final TextureAtlasSprite f_111295_;
private final boolean f_111296_;
+ private final boolean hasAmbientOcclusion;
public BakedQuad(int[] p_111298_, int p_111299_, Direction p_111300_, TextureAtlasSprite p_111301_, boolean p_111302_) {
+ this(p_111298_, p_111299_, p_111300_, p_111301_, p_111302_, true);
+ }
+
+ public BakedQuad(int[] p_111298_, int p_111299_, Direction p_111300_, TextureAtlasSprite p_111301_, boolean p_111302_, boolean hasAmbientOcclusion) {
this.f_111292_ = p_111298_;
this.f_111293_ = p_111299_;
this.f_111294_ = p_111300_;
this.f_111295_ = p_111301_;
this.f_111296_ = p_111302_;
+ this.hasAmbientOcclusion = hasAmbientOcclusion;
}
public TextureAtlasSprite m_173410_() {
@@ -43,5 +_,9 @@
public boolean m_111307_() {
return this.f_111296_;
+ }
+
+ public boolean hasAmbientOcclusion() {
+ return this.hasAmbientOcclusion;
}
}
@@ -1,25 +1,31 @@
--- a/net/minecraft/client/renderer/block/model/BlockElementFace.java
+++ b/net/minecraft/client/renderer/block/model/BlockElementFace.java
@@ -19,12 +_,18 @@
@@ -19,12 +_,24 @@
public final int f_111355_;
public final String f_111356_;
public final BlockFaceUV f_111357_;
+ public final int emissivity;
+ public final boolean hasAmbientOcclusion;
public BlockElementFace(@Nullable Direction p_111359_, int p_111360_, String p_111361_, BlockFaceUV p_111362_) {
+ this(p_111359_, p_111360_, p_111361_, p_111362_, 0);
+ this(p_111359_, p_111360_, p_111361_, p_111362_, 0, true);
+ }
+
+ public BlockElementFace(@Nullable Direction p_111359_, int p_111360_, String p_111361_, BlockFaceUV p_111362_, int emissivity) {
+ this(p_111359_, p_111360_, p_111361_, p_111362_, emissivity, true);
+ }
+
+ public BlockElementFace(@Nullable Direction p_111359_, int p_111360_, String p_111361_, BlockFaceUV p_111362_, int emissivity, boolean hasAmbientOcclusion) {
this.f_111354_ = p_111359_;
this.f_111355_ = p_111360_;
this.f_111356_ = p_111361_;
this.f_111357_ = p_111362_;
+ this.emissivity = emissivity;
+ this.hasAmbientOcclusion = hasAmbientOcclusion;
}
@OnlyIn(Dist.CLIENT)
@@ -37,7 +_,10 @@
@@ -37,7 +_,11 @@
int i = this.m_111368_(jsonobject);
String s = this.m_111370_(jsonobject);
BlockFaceUV blockfaceuv = p_111367_.deserialize(jsonobject, BlockFaceUV.class);
@@ -27,7 +33,8 @@
+ int emissivity = GsonHelper.m_13824_(jsonobject, "emissivity", 0);
+ if (emissivity != net.minecraft.util.Mth.m_14045_(emissivity, 0, 15))
+ throw new JsonParseException("The emissivity value must be between 0 and 15. Found: " + emissivity);
+ return new BlockElementFace(direction, i, s, blockfaceuv, emissivity);
+ boolean hasAmbientOcclusion = GsonHelper.m_13855_(jsonobject, "ambientocclusion", true);
+ return new BlockElementFace(direction, i, s, blockfaceuv, emissivity, hasAmbientOcclusion);
}
protected int m_111368_(JsonObject p_111369_) {
@@ -49,7 +49,7 @@
for(BlockElement blockelement : this.m_111436_()) {
for(BlockElementFace blockelementface : blockelement.f_111310_.values()) {
Material material = this.m_111480_(blockelementface.f_111356_);
@@ -181,11 +_,17 @@
@@ -181,11 +_,18 @@
return set1;
}
@@ -62,20 +62,12 @@
+ return net.minecraftforge.client.model.geometry.UnbakedGeometryHelper.bake(this, p_111450_, p_111451_, p_111452_, p_111453_, p_111454_, p_111455_);
+ }
+
+ @Deprecated //Forge: exposed for our callbacks only. Use the above function.
+ @Deprecated(forRemoval = true, since = "1.19.2") // TODO: We cannot remove it since it's vanilla code, but make it private in 1.20
+ public BakedModel bakeVanilla(ModelBakery p_111450_, BlockModel p_111451_, Function<Material, TextureAtlasSprite> p_111452_, ModelState p_111453_, ResourceLocation p_111454_, boolean p_111455_, net.minecraftforge.client.RenderTypeGroup renderTypes) {
+ if (true) return net.minecraftforge.client.model.geometry.UnbakedGeometryHelper.bakeVanilla(this, p_111450_, p_111451_, p_111452_, p_111453_, p_111454_); // Redirected, in case anyone actually uses this
TextureAtlasSprite textureatlassprite = p_111452_.apply(this.m_111480_("particle"));
if (this.m_111490_() == ModelBakery.f_119233_) {
return new BuiltInModel(this.m_111491_(), this.m_111446_(p_111450_, p_111451_), textureatlassprite, this.m_111479_().m_111526_());
@@ -204,7 +_,7 @@
}
}
- return simplebakedmodel$builder.m_119533_();
+ return simplebakedmodel$builder.build(renderTypes);
}
}
@@ -268,7 +_,18 @@
ItemTransform itemtransform5 = this.m_111444_(ItemTransforms.TransformType.GUI);
ItemTransform itemtransform6 = this.m_111444_(ItemTransforms.TransformType.GROUND);
@@ -6,7 +6,7 @@
- return new BakedQuad(aint, p_111603_.f_111355_, direction, p_111604_, p_111608_);
+ net.minecraftforge.client.ForgeHooksClient.fillNormal(aint, direction);
+ var quad = new BakedQuad(aint, p_111603_.f_111355_, direction, p_111604_, p_111608_);
+ var quad = new BakedQuad(aint, p_111603_.f_111355_, direction, p_111604_, p_111608_, p_111603_.hasAmbientOcclusion);
+ net.minecraftforge.client.model.QuadTransformers.settingEmissivity(p_111603_.emissivity).processInPlace(quad);
+ return quad;
}
@@ -88,7 +88,7 @@
if (blockstate.m_60799_() != RenderShape.INVISIBLE) {
- RenderType rendertype2 = ItemBlockRenderTypes.m_109282_(blockstate);
+ var model = blockrenderdispatcher.m_110910_(blockstate);
+ var modelData = getModelData(blockpos2);
+ var modelData = model.getModelData(renderchunkregion, blockpos2, blockstate, getModelData(blockpos2));
+ randomsource.m_188584_(blockstate.m_60726_(blockpos2));
+ for (RenderType rendertype2 : model.getRenderTypes(blockstate, randomsource, modelData)) {
BufferBuilder bufferbuilder2 = p_234471_.m_108839_(rendertype2);
@@ -99,7 +99,7 @@
posestack.m_85836_();
posestack.m_85837_((double)(blockpos2.m_123341_() & 15), (double)(blockpos2.m_123342_() & 15), (double)(blockpos2.m_123343_() & 15));
- blockrenderdispatcher.m_234355_(blockstate, blockpos2, renderchunkregion, posestack, bufferbuilder2, true, randomsource);
+ blockrenderdispatcher.renderBatched(blockstate, blockpos2, renderchunkregion, posestack, bufferbuilder2, true, randomsource, modelData, rendertype2);
+ blockrenderdispatcher.renderBatched(blockstate, blockpos2, renderchunkregion, posestack, bufferbuilder2, true, randomsource, modelData, rendertype2, false);
posestack.m_85849_();
+ }
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/renderer/chunk/RenderChunkRegion.java
+++ b/net/minecraft/client/renderer/chunk/RenderChunkRegion.java
@@ -66,4 +_,9 @@
@@ -66,4 +_,14 @@
public int m_141928_() {
return this.f_112908_.m_141928_();
}
@@ -8,5 +8,10 @@
+ @Override
+ public float getShade(float normalX, float normalY, float normalZ, boolean shade) {
+ return this.f_112908_.getShade(normalX, normalY, normalZ, shade);
+ }
+
+ @Override
+ public net.minecraftforge.client.model.data.ModelDataManager getModelDataManager() {
+ return f_112908_.getModelDataManager();
+ }
}
@@ -8,4 +8,4 @@
+public class CommandSourceStack implements SharedSuggestionProvider, net.minecraftforge.common.extensions.IForgeCommandSourceStack {
public static final SimpleCommandExceptionType f_81286_ = new SimpleCommandExceptionType(Component.m_237115_("permissions.requires.player"));
public static final SimpleCommandExceptionType f_81287_ = new SimpleCommandExceptionType(Component.m_237115_("permissions.requires.entity"));
private final CommandSource f_81288_;
public final CommandSource f_81288_;
@@ -51,5 +51,5 @@
+
+ @Override public int getIndex() { return Integer.MAX_VALUE; }
+ @Override public ResourceLocation getName() { return m_132042_(); }
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return this.f_132030_; }
+ @Override public FriendlyByteBuf getInternalData() { return m_132045_(); }
}
@@ -1,5 +1,14 @@
--- a/net/minecraft/resources/RegistryLoader.java
+++ b/net/minecraft/resources/RegistryLoader.java
@@ -26,7 +_,7 @@
Map<ResourceKey<E>, RegistryResourceAccess.EntryThunk<E>> map = this.f_206750_.m_214030_(p_206764_);
DataResult<WritableRegistry<E>> dataresult = DataResult.success(p_206763_, Lifecycle.stable());
- for(Map.Entry<ResourceKey<E>, RegistryResourceAccess.EntryThunk<E>> entry : map.entrySet()) {
+ for(Map.Entry<ResourceKey<E>, RegistryResourceAccess.EntryThunk<E>> entry : net.minecraftforge.common.ForgeHooks.filterThunks(map)) {
dataresult = dataresult.flatMap((p_214227_) -> {
return this.m_214228_(p_214227_, p_206764_, p_206765_, entry.getKey(), Optional.of(entry.getValue()), p_206766_).map((p_206761_) -> {
return p_214227_;
@@ -48,7 +_,12 @@
if (dataresult != null) {
return dataresult;
@@ -20,11 +20,26 @@
boolean flag = false;
AdvancementProgress advancementprogress = this.m_135996_(p_135989_);
boolean flag1 = advancementprogress.m_8193_();
@@ -248,6 +_,7 @@
@@ -243,11 +_,14 @@
this.m_136008_(p_135989_);
this.f_135967_.add(p_135989_);
flag = true;
+ net.minecraftforge.event.ForgeEventFactory.onAdvancementProgressedEvent(this.f_135968_, p_135989_, advancementprogress, p_135990_, net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType.GRANT);
if (!flag1 && advancementprogress.m_8193_()) {
p_135989_.m_138321_().m_9989_(this.f_135968_);
if (p_135989_.m_138320_() != null && p_135989_.m_138320_().m_14996_() && this.f_135968_.f_19853_.m_46469_().m_46207_(GameRules.f_46153_)) {
this.f_135962_.m_240416_(Component.m_237110_("chat.type.advancement." + p_135989_.m_138320_().m_14992_().m_15548_(), this.f_135968_.m_5446_(), p_135989_.m_138330_()), false);
}
+ net.minecraftforge.common.ForgeHooks.onAdvancement(this.f_135968_, p_135989_);
+ net.minecraftforge.event.ForgeEventFactory.onAdvancementEarnedEvent(this.f_135968_, p_135989_);
}
}
@@ -265,6 +_,7 @@
this.m_136004_(p_135999_);
this.f_135967_.add(p_135999_);
flag = true;
+ net.minecraftforge.event.ForgeEventFactory.onAdvancementProgressedEvent(this.f_135968_, p_135999_, advancementprogress, p_136000_, net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType.REVOKE);
}
if (!advancementprogress.m_8206_()) {
@@ -76,7 +76,7 @@
return !component.equals(p_238202_) ? p_238202_ : null;
});
completablefuture.thenAcceptAsync((p_242747_) -> {
@@ -1532,11 +_,13 @@
@@ -1532,9 +_,10 @@
return;
}
@@ -87,11 +87,16 @@
+ if(!ServerGamePacketListenerImpl.this.f_9743_.canInteractWith(entity, 1.5D)) return; //Forge: If the entity cannot be reached, do nothing. Original check was dist < 6, range is 4.5, so vanilla used padding=1.5
ItemStack itemstack = ServerGamePacketListenerImpl.this.f_9743_.m_21120_(p_143679_).m_41777_();
InteractionResult interactionresult = p_143680_.m_143694_(ServerGamePacketListenerImpl.this.f_9743_, entity, p_143679_);
+ if (net.minecraftforge.common.ForgeHooks.onInteractEntityAt(f_9743_, entity, entity.m_20182_(), p_143679_) != null) return;
if (interactionresult.m_19077_()) {
CriteriaTriggers.f_10565_.m_61494_(ServerGamePacketListenerImpl.this.f_9743_, itemstack, entity);
if (interactionresult.m_19080_()) {
@@ -1558,6 +_,8 @@
@@ -1552,12 +_,16 @@
public void m_142143_(InteractionHand p_143682_, Vec3 p_143683_) {
this.m_143678_(p_143682_, (p_143686_, p_143687_, p_143688_) -> {
+ InteractionResult onInteractEntityAtResult = net.minecraftforge.common.ForgeHooks.onInteractEntityAt(f_9743_, entity, p_143683_, p_143682_);
+ if (onInteractEntityAtResult != null) return onInteractEntityAtResult;
return p_143687_.m_7111_(p_143686_, p_143683_, p_143688_);
});
}
public void m_141994_() {
if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.f_9743_) {
@@ -54,7 +54,7 @@
};
+ }
+
+ private final net.minecraftforge.resource.ResourceCacheManager cacheManager = new net.minecraftforge.resource.ResourceCacheManager(false, net.minecraftforge.common.ForgeConfig.COMMON.indexVanillaPackCachesOnThread, (packType, namespace) -> f_182296_.get(packType).resolve(namespace));
+ private final net.minecraftforge.resource.ResourceCacheManager cacheManager = new net.minecraftforge.resource.ResourceCacheManager(false, "indexVanillaPackCachesOnThread", (packType, namespace) -> f_182296_.get(packType).resolve(namespace));
+
+ @Override
+ public void initForNamespace(final String nameSpace) {
@@ -1,12 +0,0 @@
--- a/net/minecraft/server/packs/resources/FallbackResourceManager.java
+++ b/net/minecraft/server/packs/resources/FallbackResourceManager.java
@@ -53,6 +_,9 @@
private void m_215395_(String p_215396_, @Nullable PackResources p_215397_, @Nullable Predicate<ResourceLocation> p_215398_) {
this.f_10599_.add(new FallbackResourceManager.PackEntry(p_215396_, p_215397_, p_215398_));
+ if (p_215397_ != null) {
+ p_215397_.initForNamespace(this.f_10602_);
+ }
}
public Set<String> m_7187_() {
@@ -209,6 +209,15 @@
}
}
@@ -1175,7 +_,7 @@
for(InteractionHand interactionhand : InteractionHand.values()) {
ItemStack itemstack1 = this.m_21120_(interactionhand);
- if (itemstack1.m_150930_(Items.f_42747_)) {
+ if (itemstack1.m_150930_(Items.f_42747_) && net.minecraftforge.common.ForgeHooks.onLivingUseTotem(this, p_21263_, itemstack1, interactionhand)) {
itemstack = itemstack1.m_41777_();
itemstack1.m_41774_(1);
break;
@@ -1185,7 +_,7 @@
if (itemstack != null) {
if (this instanceof ServerPlayer) {
@@ -699,7 +708,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
+ if (this.m_6084_() && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
+ if (facing == null) return handlers[2].cast();
+ else if (facing.m_122434_().m_122478_()) return handlers[0].cast();
+ else if (facing.m_122434_().m_122479_()) return handlers[1].cast();
@@ -1,10 +1,15 @@
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -211,6 +_,7 @@
@@ -210,7 +_,11 @@
}
public void m_6710_(@Nullable LivingEntity p_21544_) {
this.f_21362_ = p_21544_;
+ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(this, p_21544_);
- this.f_21362_ = p_21544_;
+ net.minecraftforge.event.entity.living.LivingChangeTargetEvent changeTargetEvent = net.minecraftforge.common.ForgeHooks.onLivingChangeTarget(this, p_21544_, net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.MOB_TARGET);
+ if(!changeTargetEvent.isCanceled()) {
+ this.f_21362_ = changeTargetEvent.getNewTarget();
+ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(this, this.f_21362_); // TODO: Remove in 1.20
+ }
}
public boolean m_6549_(EntityType<?> p_21399_) {
@@ -1,6 +1,14 @@
--- a/net/minecraft/world/entity/SpawnPlacements.java
+++ b/net/minecraft/world/entity/SpawnPlacements.java
@@ -156,10 +_,26 @@
@@ -42,6 +_,7 @@
public class SpawnPlacements {
private static final Map<EntityType<?>, SpawnPlacements.Data> f_21750_ = Maps.newHashMap();
+ @Deprecated // FORGE: use SpawnPlacementRegisterEvent to register and modify spawn placements
public static <T extends Mob> void m_21754_(EntityType<T> p_21755_, SpawnPlacements.Type p_21756_, Heightmap.Types p_21757_, SpawnPlacements.SpawnPredicate<T> p_21758_) {
SpawnPlacements.Data spawnplacements$data = f_21750_.put(p_21755_, new SpawnPlacements.Data(p_21757_, p_21756_, p_21758_));
if (spawnplacements$data != null) {
@@ -156,10 +_,35 @@
boolean m_217080_(EntityType<T> p_217081_, ServerLevelAccessor p_217082_, MobSpawnType p_217083_, BlockPos p_217084_, RandomSource p_217085_);
}
@@ -26,5 +34,14 @@
+ if (predicate == null) return net.minecraft.world.level.NaturalSpawner.canSpawnAtBody(this, world, pos, type);
+ return predicate.test(world, pos, type);
+ }
+ }
+
+ // ******* FORGE START. INTERNAL USE ONLY! ****** //
+ public static void fireSpawnPlacementEvent()
+ {
+ Map<EntityType<?>, net.minecraftforge.event.entity.SpawnPlacementRegisterEvent.MergedSpawnPredicate<?>> map = Maps.newHashMap();
+ f_21750_.forEach((type, data) -> map.put(type, new net.minecraftforge.event.entity.SpawnPlacementRegisterEvent.MergedSpawnPredicate<>(data.f_21769_, data.f_21768_, data.f_21767_)));
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.event.entity.SpawnPlacementRegisterEvent(map));
+ map.forEach(((entityType, merged) -> f_21750_.put(entityType, new SpawnPlacements.Data(merged.getHeightmapType(), merged.getSpawnType(), merged.build()))));
}
}
@@ -0,0 +1,16 @@
--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java
+++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java
@@ -46,7 +_,11 @@
}
public static <E extends Mob> void m_24213_(E p_24214_, LivingEntity p_24215_) {
- p_24214_.m_6274_().m_21879_(MemoryModuleType.f_26372_, p_24215_);
- p_24214_.m_6274_().m_21936_(MemoryModuleType.f_26326_);
+ net.minecraftforge.event.entity.living.LivingChangeTargetEvent changeTargetEvent = net.minecraftforge.common.ForgeHooks.onLivingChangeTarget(p_24214_, p_24215_, net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET);
+ if(!changeTargetEvent.isCanceled()) {
+ p_24214_.m_6274_().m_21879_(MemoryModuleType.f_26372_, changeTargetEvent.getNewTarget());
+ p_24214_.m_6274_().m_21936_(MemoryModuleType.f_26326_);
+ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(p_24214_, changeTargetEvent.getNewTarget(), net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET); // TODO: Remove in 1.20
+ }
}
}
@@ -1,11 +1,12 @@
--- a/net/minecraft/world/entity/animal/Cat.java
+++ b/net/minecraft/world/entity/animal/Cat.java
@@ -366,7 +_,7 @@
@@ -365,8 +_,8 @@
if (this.m_21830_(p_28153_)) {
if (!(item instanceof DyeItem)) {
if (item.m_41472_() && this.m_6898_(itemstack) && this.m_21223_() < this.m_21233_()) {
+ this.m_5634_((float)itemstack.getFoodProperties(this).m_38744_());
this.m_142075_(p_28153_, p_28154_, itemstack);
- this.m_5634_((float)item.m_41473_().m_38744_());
+ this.m_5634_((float)itemstack.getFoodProperties(this).m_38744_());
return InteractionResult.CONSUME;
}
@@ -1,11 +1,15 @@
--- a/net/minecraft/world/entity/animal/Wolf.java
+++ b/net/minecraft/world/entity/animal/Wolf.java
@@ -329,7 +_,8 @@
@@ -325,11 +_,12 @@
} else {
if (this.m_21824_()) {
if (this.m_6898_(itemstack) && this.m_21223_() < this.m_21233_()) {
+ this.m_5634_((float)itemstack.getFoodProperties(this).m_38744_());
if (!p_30412_.m_150110_().f_35937_) {
itemstack.m_41774_(1);
}
- this.m_5634_((float)item.m_41473_().m_38744_());
+ this.m_5634_((float)itemstack.getFoodProperties(this).m_38744_());
+ this.m_146852_(GameEvent.f_157806_, this);
return InteractionResult.SUCCESS;
}
@@ -38,7 +38,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
+ if (this.m_6084_() && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && itemHandler != null)
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && itemHandler != null)
+ return itemHandler.cast();
+ return super.getCapability(capability, facing);
+ }
@@ -1,5 +1,14 @@
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -129,7 +_,7 @@
for(int k = 0; k < 9; ++k) {
int l = (this.f_35977_ + k) % 9;
- if (!this.f_35974_.get(l).m_41793_()) {
+ if (!this.f_35974_.get(l).isNotReplaceableByPickAction(this.f_35978_, l)) {
return l;
}
}
@@ -177,7 +_,8 @@
int i = p_36049_.m_41613_();
ItemStack itemstack = this.m_8020_(p_36048_);
@@ -215,7 +215,11 @@
if (p_36347_.m_6097_()) {
if (!p_36347_.m_7313_(this)) {
float f = (float)this.m_21133_(Attributes.f_22281_);
@@ -1086,7 +_,7 @@
@@ -1082,11 +_,10 @@
float f2 = this.m_36403_(0.5F);
f *= 0.2F + f2 * f2 * 0.8F;
f1 *= f2;
- this.m_36334_();
if (f > 0.0F || f1 > 0.0F) {
boolean flag = f2 > 0.9F;
boolean flag1 = false;
@@ -276,6 +280,14 @@
this.m_21008_(InteractionHand.MAIN_HAND, ItemStack.f_41583_);
}
}
@@ -1212,6 +_,7 @@
}
}
}
+ this.m_36334_(); // FORGE: Moved from beginning of attack() so that getAttackStrengthScale() returns an accurate value during all attack events
}
}
@@ -1228,7 +_,7 @@
}
@@ -431,7 +443,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
+ if (this.m_6084_() && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
+ if (facing == null) return playerJoinedHandler.cast();
+ else if (facing.m_122434_().m_122478_()) return playerMainHandler.cast();
+ else if (facing.m_122434_().m_122479_()) return playerEquipmentHandler.cast();
@@ -5,7 +5,7 @@
if (!this.f_19853_.f_46443_) {
Entity entity = this.m_37282_();
- if (!(entity instanceof Mob) || this.f_19853_.m_46469_().m_46207_(GameRules.f_46132_)) {
+ if (!(entity instanceof Mob) || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.f_19853_, this)) {
+ if (!(entity instanceof Mob) || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.f_19853_, entity)) {
BlockPos blockpos = p_37384_.m_82425_().m_121945_(p_37384_.m_82434_());
if (this.f_19853_.m_46859_(blockpos)) {
this.f_19853_.m_46597_(blockpos, BaseFireBlock.m_49245_(this.f_19853_, blockpos));
@@ -4,7 +4,7 @@
if (entity instanceof ServerPlayer) {
ServerPlayer serverplayer = (ServerPlayer)entity;
if (serverplayer.f_8906_.m_6198_().m_129536_() && serverplayer.f_19853_ == this.f_19853_ && !serverplayer.m_5803_()) {
+ net.minecraftforge.event.entity.EntityTeleportEvent.EnderPearl event = net.minecraftforge.event.ForgeEventFactory.onEnderPearlLand(serverplayer, this.m_20185_(), this.m_20186_(), this.m_20189_(), this, 5.0F);
+ net.minecraftforge.event.entity.EntityTeleportEvent.EnderPearl event = net.minecraftforge.event.ForgeEventFactory.onEnderPearlLand(serverplayer, this.m_20185_(), this.m_20186_(), this.m_20189_(), this, 5.0F, p_37504_);
+ if (!event.isCanceled()) { // Don't indent to lower patch size
if (this.f_19796_.m_188501_() < 0.05F && this.f_19853_.m_46469_().m_46207_(GameRules.f_46134_)) {
Endermite endermite = EntityType.f_20567_.m_20615_(this.f_19853_);
@@ -110,7 +110,7 @@
}
}
@@ -390,7 +_,8 @@
@@ -390,18 +_,19 @@
d1 = (double)p_38156_.m_123342_();
boolean flag = false;
boolean flag1 = false;
@@ -120,7 +120,11 @@
flag = p_38157_.m_61143_(PoweredRailBlock.f_55215_);
flag1 = !flag;
}
@@ -401,22 +_,22 @@
- double d3 = 0.0078125D;
+ double d3 = getSlopeAdjustment();
if (this.m_20069_()) {
d3 *= 0.2D;
}
Vec3 vec31 = this.m_20184_();
@@ -128,26 +132,7 @@
+ RailShape railshape = ((BaseRailBlock)p_38157_.m_60734_()).getRailDirection(p_38157_, this.f_19853_, p_38156_, this);
switch (railshape) {
case ASCENDING_EAST:
- this.m_20256_(vec31.m_82520_(-d3, 0.0D, 0.0D));
+ this.m_20256_(vec31.m_82520_(-1 * getSlopeAdjustment(), 0.0D, 0.0D));
++d1;
break;
case ASCENDING_WEST:
- this.m_20256_(vec31.m_82520_(d3, 0.0D, 0.0D));
+ this.m_20256_(vec31.m_82520_(getSlopeAdjustment(), 0.0D, 0.0D));
++d1;
break;
case ASCENDING_NORTH:
- this.m_20256_(vec31.m_82520_(0.0D, 0.0D, d3));
+ this.m_20256_(vec31.m_82520_(0.0D, 0.0D, getSlopeAdjustment()));
++d1;
break;
case ASCENDING_SOUTH:
- this.m_20256_(vec31.m_82520_(0.0D, 0.0D, -d3));
+ this.m_20256_(vec31.m_82520_(0.0D, 0.0D, -1 * getSlopeAdjustment()));
++d1;
}
this.m_20256_(vec31.m_82520_(-d3, 0.0D, 0.0D));
@@ -447,7 +_,7 @@
}
}
@@ -236,8 +221,8 @@
+ private float currentSpeedCapOnRail = getMaxCartSpeedOnRail();
+ @Override public float getCurrentCartSpeedCapOnRail() { return currentSpeedCapOnRail; }
+ @Override public void setCurrentCartSpeedCapOnRail(float value) { currentSpeedCapOnRail = Math.min(value, getMaxCartSpeedOnRail()); }
+ private float maxSpeedAirLateral = DEFAULT_MAX_SPEED_AIR_LATERAL;
+ @Override public float getMaxSpeedAirLateral() { return maxSpeedAirLateral; }
+ @org.jetbrains.annotations.Nullable private Float maxSpeedAirLateral = null;
+ @Override public float getMaxSpeedAirLateral() { return maxSpeedAirLateral == null ? (float) this.m_7097_() : maxSpeedAirLateral; }
+ @Override public void setMaxSpeedAirLateral(float value) { maxSpeedAirLateral = value; }
+ private float maxSpeedAirVertical = DEFAULT_MAX_SPEED_AIR_VERTICAL;
+ @Override public float getMaxSpeedAirVertical() { return maxSpeedAirVertical; }
@@ -19,7 +19,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
+ if (this.m_6084_() && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
+ return itemHandler.cast();
+ return super.getCapability(capability, facing);
+ }
@@ -10,7 +10,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
+ if (this.m_6084_() && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
+ return itemHandler.cast();
+ return super.getCapability(capability, facing);
+ }
@@ -12,6 +12,14 @@
for(ContainerListener containerlistener : this.f_38848_) {
containerlistener.m_7934_(this, p_150408_, itemstack1);
}
@@ -400,6 +_,7 @@
ItemStack itemstack11 = this.m_142621_();
p_150434_.m_141945_(itemstack11, slot7.m_7993_(), clickaction);
if (!itemstack11.m_150926_(slot7, clickaction, p_150434_) && !itemstack10.m_150932_(itemstack11, slot7, clickaction, p_150434_, this.m_150446_())) {
+ if (!net.minecraftforge.common.ForgeHooks.onItemStackedOn(itemstack11, itemstack10, slot7, clickaction, p_150434_, m_150446_()))
if (itemstack10.m_41619_()) {
if (!itemstack11.m_41619_()) {
int l2 = clickaction == ClickAction.PRIMARY ? itemstack11.m_41613_() : 1;
@@ -601,14 +_,15 @@
ItemStack itemstack = slot.m_7993_();
if (!itemstack.m_41619_() && ItemStack.m_150942_(p_38904_, itemstack)) {
@@ -1,5 +1,53 @@
--- a/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -34,6 +_,7 @@
}
};
private final ContainerLevelAccess f_39561_;
+ private int xp = -1;
public GrindstoneMenu(int p_39563_, Inventory p_39564_) {
this(p_39563_, p_39564_, ContainerLevelAccess.f_39287_);
@@ -44,12 +_,12 @@
this.f_39561_ = p_39568_;
this.m_38897_(new Slot(this.f_39560_, 0, 49, 19) {
public boolean m_5857_(ItemStack p_39607_) {
- return p_39607_.m_41763_() || p_39607_.m_150930_(Items.f_42690_) || p_39607_.m_41793_();
+ return true; //Allow all items in the slot, not just repairable
}
});
this.m_38897_(new Slot(this.f_39560_, 1, 49, 40) {
public boolean m_5857_(ItemStack p_39616_) {
- return p_39616_.m_41763_() || p_39616_.m_150930_(Items.f_42690_) || p_39616_.m_41793_();
+ return true; //Allow all items in the slot, not just repairable
}
});
this.m_38897_(new Slot(this.f_39559_, 2, 129, 34) {
@@ -58,6 +_,7 @@
}
public void m_142406_(Player p_150574_, ItemStack p_150575_) {
+ if (net.minecraftforge.common.ForgeHooks.onGrindstoneTake(GrindstoneMenu.this.f_39560_, p_39568_, this::m_39631_)) return;
p_39568_.m_39292_((p_39634_, p_39635_) -> {
if (p_39634_ instanceof ServerLevel) {
ExperienceOrb.m_147082_((ServerLevel)p_39634_, Vec3.m_82512_(p_39635_), this.m_39631_(p_39634_));
@@ -70,6 +_,7 @@
}
private int m_39631_(Level p_39632_) {
+ if (xp > -1) return xp;
int l = 0;
l += this.m_39636_(GrindstoneMenu.this.f_39560_.m_8020_(0));
l += this.m_39636_(GrindstoneMenu.this.f_39560_.m_8020_(1));
@@ -122,6 +_,8 @@
ItemStack itemstack1 = this.f_39560_.m_8020_(1);
boolean flag = !itemstack.m_41619_() || !itemstack1.m_41619_();
boolean flag1 = !itemstack.m_41619_() && !itemstack1.m_41619_();
+ this.xp = net.minecraftforge.common.ForgeHooks.onGrindstoneChange(itemstack, itemstack1, this.f_39559_, -1);
+ if (this.xp == Integer.MIN_VALUE)
if (!flag) {
this.f_39559_.m_6836_(0, ItemStack.f_41583_);
} else {
@@ -143,12 +_,13 @@
}
@@ -8,3 +8,12 @@
if (optional.isPresent()) {
optional.get().m_77743_();
return;
@@ -170,7 +_,7 @@
boolean flag = false;
for(Direction direction : Direction.values()) {
- if (p_49270_.m_8055_(blockpos$mutableblockpos.m_122190_(p_49271_).m_122173_(direction)).m_60713_(Blocks.f_50080_)) {
+ if (p_49270_.m_8055_(blockpos$mutableblockpos.m_122190_(p_49271_).m_122173_(direction)).isPortalFrame(p_49270_, blockpos$mutableblockpos)) {
flag = true;
break;
}
@@ -35,30 +35,31 @@
p_49385_.m_46672_(p_49386_.m_7494_(), this);
}
@@ -139,6 +_,7 @@
@@ -139,6 +_,11 @@
return blockstate.m_61124_(this.m_7978_(), flag1 ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH).m_61124_(f_152149_, Boolean.valueOf(flag));
}
+ @Deprecated //Forge: Use getRailDirection(IBlockAccess, BlockPos, IBlockState, EntityMinecart) for enhanced ability
+ /**
+ * @deprecated Forge: Use {@link BaseRailBlock#getRailDirection(BlockState, BlockGetter, BlockPos, net.minecraft.world.entity.vehicle.AbstractMinecart)} for enhanced ability
+ * If you do change this property be aware that other functions in this/subclasses may break as they can make assumptions about this property
+ */
+ @Deprecated
public abstract Property<RailShape> m_7978_();
public BlockState m_7417_(BlockState p_152151_, Direction p_152152_, BlockState p_152153_, LevelAccessor p_152154_, BlockPos p_152155_, BlockPos p_152156_) {
@@ -152,4 +_,18 @@
@@ -151,5 +_,15 @@
public FluidState m_5888_(BlockState p_152158_) {
return p_152158_.m_61143_(f_152149_) ? Fluids.f_76193_.m_76068_(false) : super.m_5888_(p_152158_);
+ }
+
+ @Override
+ public boolean isFlexibleRail(BlockState state, BlockGetter world, BlockPos pos) {
+ return !this.f_49357_;
+ }
+
+ @Override
+ public RailShape getRailDirection(BlockState state, BlockGetter world, BlockPos pos, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.vehicle.AbstractMinecart cart) {
+ return state.m_61143_(m_7978_());
}
+
+ /* ======================================== FORGE START =====================================*/
+
+ @Override
+ public boolean isFlexibleRail(BlockState state, BlockGetter world, BlockPos pos)
+ {
+ return !this.f_49357_;
+ }
+
+ @Override
+ public RailShape getRailDirection(BlockState state, BlockGetter world, BlockPos pos, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.vehicle.AbstractMinecart cart) {
+ return state.m_61143_(m_7978_());
+ }
+ /* ========================================= FORGE END ======================================*/
}
@@ -1,5 +1,16 @@
--- a/net/minecraft/world/level/block/DetectorRailBlock.java
+++ b/net/minecraft/world/level/block/DetectorRailBlock.java
@@ -31,6 +_,10 @@
public DetectorRailBlock(BlockBehaviour.Properties p_52431_) {
super(true, p_52431_);
+ this.registerDefaultState();
+ }
+
+ protected void registerDefaultState() {
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_52428_, Boolean.valueOf(false)).m_61124_(f_52427_, RailShape.NORTH_SOUTH).m_61124_(f_152149_, Boolean.valueOf(false)));
}
@@ -135,7 +_,9 @@
return list.get(0).m_38534_().m_45436_();
}
@@ -11,3 +22,11 @@
if (!list1.isEmpty()) {
return AbstractContainerMenu.m_38938_((Container)list1.get(0));
}
@@ -270,6 +_,6 @@
}
protected void m_7926_(StateDefinition.Builder<Block, BlockState> p_52469_) {
- p_52469_.m_61104_(f_52427_, f_52428_, f_152149_);
+ p_52469_.m_61104_(m_7978_(), f_52428_, f_152149_);
}
}
@@ -0,0 +1,41 @@
--- a/net/minecraft/world/level/block/FlowerBlock.java
+++ b/net/minecraft/world/level/block/FlowerBlock.java
@@ -15,6 +_,17 @@
private final MobEffect f_53508_;
private final int f_53509_;
+ private final java.util.function.Supplier<MobEffect> suspiciousStewEffectSupplier;
+
+ public FlowerBlock(java.util.function.Supplier<MobEffect> effectSupplier, int p_53513_, BlockBehaviour.Properties p_53514_) {
+ super(p_53514_);
+ this.f_53508_ = null;
+ this.suspiciousStewEffectSupplier = effectSupplier;
+ this.f_53509_ = p_53513_;
+ }
+
+ /** @deprecated FORGE: Use supplier version instead */
+ @Deprecated
public FlowerBlock(MobEffect p_53512_, int p_53513_, BlockBehaviour.Properties p_53514_) {
super(p_53514_);
this.f_53508_ = p_53512_;
@@ -23,6 +_,7 @@
} else {
this.f_53509_ = p_53513_ * 20;
}
+ this.suspiciousStewEffectSupplier = net.minecraftforge.registries.ForgeRegistries.MOB_EFFECTS.getDelegateOrThrow(p_53512_);
}
@@ -32,10 +_,12 @@
}
public MobEffect m_53521_() {
+ if (true) return this.suspiciousStewEffectSupplier.get();
return this.f_53508_;
}
public int m_53522_() {
+ if (this.f_53508_ == null && !this.suspiciousStewEffectSupplier.get().m_8093_()) return this.f_53509_ * 20;
return this.f_53509_;
}
}
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/FungusBlock.java
+++ b/net/minecraft/world/level/block/FungusBlock.java
@@ -44,6 +_,8 @@
}
public void m_214148_(ServerLevel p_221243_, RandomSource p_221244_, BlockPos p_221245_, BlockState p_221246_) {
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_221243_, p_221244_, p_221245_, this.f_53597_.get());
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY)) return;
this.f_53597_.get().m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
}
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/MushroomBlock.java
+++ b/net/minecraft/world/level/block/MushroomBlock.java
@@ -70,7 +_,7 @@
@@ -70,13 +_,15 @@
if (blockstate.m_204336_(BlockTags.f_13057_)) {
return true;
} else {
@@ -9,3 +9,12 @@
}
}
public boolean m_221773_(ServerLevel p_221774_, BlockPos p_221775_, BlockState p_221776_, RandomSource p_221777_) {
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_221774_, p_221777_, p_221775_, this.f_153981_.get());
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY)) return false;
p_221774_.m_7471_(p_221775_, false);
- if (this.f_153981_.get().m_203334_().m_224953_(p_221774_, p_221774_.m_7726_().m_8481_(), p_221777_, p_221775_)) {
+ if (event.getFeature().m_203334_().m_224953_(p_221774_, p_221774_.m_7726_().m_8481_(), p_221777_, p_221775_)) {
return true;
} else {
p_221774_.m_7731_(p_221775_, p_221776_, 3);
@@ -1,54 +1,78 @@
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
@@ -14,10 +_,16 @@
@@ -14,9 +_,19 @@
public class PoweredRailBlock extends BaseRailBlock {
public static final EnumProperty<RailShape> f_55214_ = BlockStateProperties.f_61404_;
public static final BooleanProperty f_55215_ = BlockStateProperties.f_61448_;
+ private final boolean isActivator; // TRUE for an Activator Rail, FALSE for Powered Rail
public PoweredRailBlock(BlockBehaviour.Properties p_55218_) {
- super(true, p_55218_);
+ this(p_55218_, false);
+ }
+
+ protected PoweredRailBlock(BlockBehaviour.Properties builder, boolean isPoweredRail) {
+ super(true, builder);
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_55214_, RailShape.NORTH_SOUTH).m_61124_(f_55215_, Boolean.valueOf(false)).m_61124_(f_152149_, Boolean.valueOf(false)));
+ protected PoweredRailBlock(BlockBehaviour.Properties p_55218_, boolean isPoweredRail) {
super(true, p_55218_);
+ this.isActivator = !isPoweredRail;
+ this.registerDefaultState();
+ }
+
+ protected void registerDefaultState() {
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_55214_, RailShape.NORTH_SOUTH).m_61124_(f_55215_, Boolean.valueOf(false)).m_61124_(f_152149_, Boolean.valueOf(false)));
}
protected boolean m_55219_(Level p_55220_, BlockPos p_55221_, BlockState p_55222_, boolean p_55223_, int p_55224_) {
@@ -99,13 +_,13 @@
@@ -28,7 +_,7 @@
int j = p_55221_.m_123342_();
int k = p_55221_.m_123343_();
boolean flag = true;
- RailShape railshape = p_55222_.m_61143_(f_55214_);
+ RailShape railshape = p_55222_.m_61143_(m_7978_());
switch (railshape) {
case NORTH_SOUTH:
if (p_55223_) {
@@ -99,14 +_,14 @@
protected boolean m_55225_(Level p_55226_, BlockPos p_55227_, boolean p_55228_, int p_55229_, RailShape p_55230_) {
BlockState blockstate = p_55226_.m_8055_(p_55227_);
- if (!blockstate.m_60713_(this)) {
+ if (!(blockstate.m_60734_() instanceof PoweredRailBlock)) {
+ if (!(blockstate.m_60734_() instanceof PoweredRailBlock other)) {
return false;
} else {
- RailShape railshape = blockstate.m_61143_(f_55214_);
+ RailShape railshape = getRailDirection(blockstate, p_55226_, p_55227_, null);
+ RailShape railshape = other.getRailDirection(blockstate, p_55226_, p_55227_, null);
if (p_55230_ != RailShape.EAST_WEST || railshape != RailShape.NORTH_SOUTH && railshape != RailShape.ASCENDING_NORTH && railshape != RailShape.ASCENDING_SOUTH) {
if (p_55230_ != RailShape.NORTH_SOUTH || railshape != RailShape.EAST_WEST && railshape != RailShape.ASCENDING_EAST && railshape != RailShape.ASCENDING_WEST) {
- if (blockstate.m_61143_(f_55215_)) {
+ if (isActivator == (((PoweredRailBlock) blockstate.m_60734_()).isActivator)) {
return p_55226_.m_46753_(p_55227_) ? true : this.m_55219_(p_55226_, p_55227_, blockstate, p_55228_, p_55229_ + 1);
- return p_55226_.m_46753_(p_55227_) ? true : this.m_55219_(p_55226_, p_55227_, blockstate, p_55228_, p_55229_ + 1);
+ if (isActivatorRail() == other.isActivatorRail()) {
+ return p_55226_.m_46753_(p_55227_) ? true : other.m_55219_(p_55226_, p_55227_, blockstate, p_55228_, p_55229_ + 1);
} else {
return false;
}
@@ -125,7 +_,7 @@
if (flag1 != flag) {
p_55233_.m_7731_(p_55234_, p_55232_.m_61124_(f_55215_, Boolean.valueOf(flag1)), 3);
p_55233_.m_46672_(p_55234_.m_7495_(), this);
- if (p_55232_.m_61143_(f_55214_).m_61745_()) {
+ if (p_55232_.m_61143_(m_7978_()).m_61745_()) {
p_55233_.m_46672_(p_55234_.m_7494_(), this);
}
}
@@ -156,6 +_,9 @@
return p_55240_.m_61124_(f_55214_, RailShape.SOUTH_EAST);
case NORTH_EAST:
return p_55240_.m_61124_(f_55214_, RailShape.SOUTH_WEST);
+ case NORTH_SOUTH: //Forge fix: MC-196102
+ case EAST_WEST:
+ return p_55240_;
+ case NORTH_SOUTH: //Forge fix: MC-196102
+ case EAST_WEST:
+ return p_55240_;
}
case COUNTERCLOCKWISE_90:
switch ((RailShape)p_55240_.m_61143_(f_55214_)) {
@@ -254,5 +_,9 @@
@@ -253,6 +_,10 @@
}
protected void m_7926_(StateDefinition.Builder<Block, BlockState> p_55243_) {
p_55243_.m_61104_(f_55214_, f_55215_, f_152149_);
- p_55243_.m_61104_(f_55214_, f_55215_, f_152149_);
+ p_55243_.m_61104_(m_7978_(), f_55215_, f_152149_);
+ }
+
+ public boolean isActivatorRail() {
@@ -1,18 +1,10 @@
--- a/net/minecraft/world/level/block/SaplingBlock.java
+++ b/net/minecraft/world/level/block/SaplingBlock.java
@@ -32,6 +_,7 @@
@@ -31,6 +_,7 @@
}
public void m_213898_(BlockState p_222011_, ServerLevel p_222012_, BlockPos p_222013_, RandomSource p_222014_) {
if (p_222012_.m_46803_(p_222013_.m_7494_()) >= 9 && p_222014_.m_188503_(7) == 0) {
+ if (!p_222012_.isAreaLoaded(p_222013_, 1)) return; // Forge: prevent loading unloaded chunks when checking neighbor's light
if (p_222012_.m_46803_(p_222013_.m_7494_()) >= 9 && p_222014_.m_188503_(7) == 0) {
this.m_222000_(p_222012_, p_222013_, p_222011_, p_222014_);
}
@@ -41,6 +_,7 @@
if (p_222003_.m_61143_(f_55973_) == 0) {
p_222001_.m_7731_(p_222002_, p_222003_.m_61122_(f_55973_), 4);
} else {
+ if (!net.minecraftforge.event.ForgeEventFactory.saplingGrowTree(p_222001_, p_222004_, p_222002_)) return;
this.f_55975_.m_213817_(p_222001_, p_222001_.m_7726_().m_8481_(), p_222002_, p_222003_, p_222004_);
}
@@ -164,7 +164,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
+ if (facing == Direction.UP)
+ return handlers[0].cast();
+ else if (facing == Direction.DOWN)
@@ -11,7 +11,7 @@
+ }
+
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, @org.jetbrains.annotations.Nullable net.minecraft.core.Direction side) {
+ if (!this.f_58859_ && cap == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY )
+ if (!this.f_58859_ && cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
+ return itemHandler.cast();
+ return super.getCapability(cap, side);
+ }
@@ -62,7 +62,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
+ if (facing == Direction.UP)
+ return handlers[0].cast();
+ else if (facing == Direction.DOWN)
@@ -17,7 +17,7 @@
+
+ @Override
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, Direction side) {
+ if (!this.f_58859_ && cap == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (!this.f_58859_ && cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
+ if (this.chestHandler == null)
+ this.chestHandler = net.minecraftforge.common.util.LazyOptional.of(this::createHandler);
+ return this.chestHandler.cast();
@@ -0,0 +1,30 @@
--- a/net/minecraft/world/level/block/grower/AbstractMegaTreeGrower.java
+++ b/net/minecraft/world/level/block/grower/AbstractMegaTreeGrower.java
@@ -25,15 +_,24 @@
return super.m_213817_(p_222891_, p_222892_, p_222893_, p_222894_, p_222895_);
}
+ // Forge: context-sensitive version to be able to use data pack provided features
+ @Nullable
+ protected Holder<? extends ConfiguredFeature<?, ?>> getConfiguredMegaFeature(ServerLevel level, ChunkGenerator chunkGenerator, BlockPos pos, BlockState state, RandomSource random) {
+ return m_213566_(random);
+ }
+
+ /** @deprecated Forge: Use {@link #getConfiguredMegaFeature(ServerLevel, ChunkGenerator, BlockPos, BlockState, RandomSource)} instead */
+ @Deprecated
@Nullable
protected abstract Holder<? extends ConfiguredFeature<?, ?>> m_213566_(RandomSource p_222904_);
public boolean m_222896_(ServerLevel p_222897_, ChunkGenerator p_222898_, BlockPos p_222899_, BlockState p_222900_, RandomSource p_222901_, int p_222902_, int p_222903_) {
- Holder<? extends ConfiguredFeature<?, ?>> holder = this.m_213566_(p_222901_);
- if (holder == null) {
+ Holder<? extends ConfiguredFeature<?, ?>> holder = this.getConfiguredMegaFeature(p_222897_, p_222898_, p_222899_, p_222900_, p_222901_);
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_222897_, p_222901_, p_222899_, holder);
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY) || event.getFeature() == null) {
return false;
} else {
- ConfiguredFeature<?, ?> configuredfeature = holder.m_203334_();
+ ConfiguredFeature<?, ?> configuredfeature = event.getFeature().m_203334_();
BlockState blockstate = Blocks.f_50016_.m_49966_();
p_222897_.m_7731_(p_222899_.m_7918_(p_222902_, 0, p_222903_), blockstate, 4);
p_222897_.m_7731_(p_222899_.m_7918_(p_222902_ + 1, 0, p_222903_), blockstate, 4);
@@ -0,0 +1,30 @@
--- a/net/minecraft/world/level/block/grower/AbstractTreeGrower.java
+++ b/net/minecraft/world/level/block/grower/AbstractTreeGrower.java
@@ -12,15 +_,24 @@
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
public abstract class AbstractTreeGrower {
+ // Forge: context-sensitive version to be able to use data pack provided features
+ @Nullable
+ protected Holder<? extends ConfiguredFeature<?, ?>> getConfiguredFeature(ServerLevel level, ChunkGenerator chunkGenerator, BlockPos pos, BlockState state, RandomSource random, boolean hasFlowers) {
+ return m_213888_(random, hasFlowers);
+ }
+
+ /** @deprecated Forge: Use {@link #getConfiguredFeature(ServerLevel, ChunkGenerator, BlockPos, BlockState, RandomSource, boolean)} instead */
+ @Deprecated
@Nullable
protected abstract Holder<? extends ConfiguredFeature<?, ?>> m_213888_(RandomSource p_222910_, boolean p_222911_);
public boolean m_213817_(ServerLevel p_222905_, ChunkGenerator p_222906_, BlockPos p_222907_, BlockState p_222908_, RandomSource p_222909_) {
- Holder<? extends ConfiguredFeature<?, ?>> holder = this.m_213888_(p_222909_, this.m_60011_(p_222905_, p_222907_));
- if (holder == null) {
+ Holder<? extends ConfiguredFeature<?, ?>> holder = this.getConfiguredFeature(p_222905_, p_222906_, p_222907_, p_222908_, p_222909_, this.m_60011_(p_222905_, p_222907_));
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_222905_, p_222909_, p_222907_, holder);
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY) || event.getFeature() == null) {
return false;
} else {
- ConfiguredFeature<?, ?> configuredfeature = holder.m_203334_();
+ ConfiguredFeature<?, ?> configuredfeature = event.getFeature().m_203334_();
BlockState blockstate = p_222905_.m_6425_(p_222907_).m_76188_();
p_222905_.m_7731_(p_222907_, blockstate, 4);
if (configuredfeature.m_224953_(p_222905_, p_222906_, p_222909_, p_222907_)) {
@@ -4,7 +4,7 @@
for(int i1 = 0; i1 < l; ++i1) {
Phantom phantom = EntityType.f_20509_.m_20615_(p_64576_);
phantom.m_20035_(blockpos1, 0.0F, 0.0F);
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(phantom, p_64576_, blockpos1.m_123341_(), blockpos1.m_123342_(), blockpos1.m_123343_(), null, MobSpawnType.NATURAL) == -1) return 0;
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(phantom, p_64576_, blockpos1.m_123341_(), blockpos1.m_123342_(), blockpos1.m_123343_(), null, MobSpawnType.NATURAL) == -1) { i--; continue; }
spawngroupdata = phantom.m_6518_(p_64576_, difficultyinstance, MobSpawnType.NATURAL, spawngroupdata, (CompoundTag)null);
p_64576_.m_47205_(phantom);
}
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java
+++ b/net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer.java
@@ -58,7 +_,7 @@
}
protected static void m_226169_(LevelSimulatedReader p_226170_, BiConsumer<BlockPos, BlockState> p_226171_, RandomSource p_226172_, BlockPos p_226173_, TreeConfiguration p_226174_) {
- if (p_226174_.f_161215_ || !m_70295_(p_226170_, p_226173_)) {
+ if (!(((net.minecraft.world.level.LevelReader) p_226170_).m_8055_(p_226173_).onTreeGrow((net.minecraft.world.level.LevelReader) p_226170_, p_226171_, p_226172_, p_226173_, p_226174_)) && (p_226174_.f_161215_ || !m_70295_(p_226170_, p_226173_))) {
p_226171_.accept(p_226173_, p_226174_.f_161212_.m_213972_(p_226172_, p_226173_));
}
@@ -23,7 +23,7 @@
+ LevelStorageSource.this.m_230817_(this.f_230867_, (path, dataFixer) -> {
+ try {
+ CompoundTag compoundTag = NbtIo.m_128937_(path.toFile());
+ net.minecraftforge.common.ForgeHooks.readAdditionalLevelSaveData(compoundTag);
+ net.minecraftforge.common.ForgeHooks.readAdditionalLevelSaveData(compoundTag, this.f_230867_);
+ } catch (Exception e) {
+ f_78191_.error("Exception reading {}", path, e);
+ }
+1
View File
@@ -13,6 +13,7 @@
<MarkerFilter marker="REGISTRIES" onMatch="${sys:forge.logging.marker.registries:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="REGISTRYDUMP" onMatch="${sys:forge.logging.marker.registrydump:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="SPLASH" onMatch="${sys:forge.logging.marker.splash:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="RESOURCE-CACHE" onMatch="${sys:forge.logging.marker.resource.cache:-DENY}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="FORGEMOD" onMatch="${sys:forge.logging.marker.forgemod:-ACCEPT}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="LOADING" onMatch="${sys:forge.logging.marker.loading:-ACCEPT}" onMismatch="NEUTRAL"/>
<MarkerFilter marker="CORE" onMatch="${sys:forge.logging.marker.core:-ACCEPT}" onMismatch="NEUTRAL"/>
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:bookshelf"
]
}
@@ -7,6 +7,7 @@
"minecraft:acacia_fence_gate",
"minecraft:dark_oak_fence_gate",
"minecraft:crimson_fence_gate",
"minecraft:warped_fence_gate"
"minecraft:warped_fence_gate",
"minecraft:mangrove_fence_gate"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"minecraft:ender_dragon",
"minecraft:wither"
]
}
@@ -7,6 +7,7 @@
"minecraft:acacia_fence_gate",
"minecraft:dark_oak_fence_gate",
"minecraft:crimson_fence_gate",
"minecraft:warped_fence_gate"
"minecraft:warped_fence_gate",
"minecraft:mangrove_fence_gate"
]
}
@@ -0,0 +1,7 @@
{
"values": [
"minecraft:lush_caves",
"minecraft:dripstone_caves",
"minecraft:deep_dark"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:desert"
]
}
@@ -1,7 +1,5 @@
{
"values": [
"minecraft:lush_caves",
"minecraft:dripstone_caves",
"minecraft:deep_dark"
"#forge:is_cave"
]
}
@@ -17,6 +17,7 @@ import com.mojang.datafixers.util.Either;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import net.minecraft.ChatFormatting;
import net.minecraft.FileUtil;
import net.minecraft.client.Camera;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
@@ -54,6 +55,7 @@ import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.texture.TextureAtlas;
@@ -560,6 +562,18 @@ public class ForgeHooksClient
return new Vector3f(x, y, z);
}
public static boolean calculateFaceWithoutAO(BlockAndTintGetter getter, BlockState state, BlockPos pos, BakedQuad quad, boolean isFaceCubic, float[] brightness, int[] lightmap)
{
if (quad.hasAmbientOcclusion())
return false;
BlockPos lightmapPos = isFaceCubic ? pos.relative(quad.getDirection()) : pos;
brightness[0] = brightness[1] = brightness[2] = brightness[3] = getter.getShade(quad.getDirection(), quad.isShade());
lightmap[0] = lightmap[1] = lightmap[2] = lightmap[3] = LevelRenderer.getLightColor(getter, state, lightmapPos);
return true;
}
public static void loadEntityShader(Entity entity, GameRenderer entityRenderer)
{
if (entity != null)
@@ -1155,4 +1169,12 @@ public class ForgeHooksClient
Mth.log2(Math.max(1, height))
);
}
public static ResourceLocation getShaderImportLocation(String basePath, boolean isRelative, String importPath)
{
final var loc = new ResourceLocation(importPath);
final var normalised = FileUtil.normalizeResourcePath(
(isRelative ? basePath : "shaders/include/") + loc.getPath());
return new ResourceLocation(loc.getNamespace(), normalised);
}
}
@@ -2,6 +2,7 @@
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.event;
import net.minecraft.world.item.Item;
@@ -0,0 +1,43 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.extensions;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Transformation;
import com.mojang.math.Vector3f;
/**
* Extension interface for {@link com.mojang.blaze3d.vertex.PoseStack}.
*/
public interface IForgePoseStack
{
private PoseStack self()
{
return (PoseStack) this;
}
/**
* Pushes and applies the {@code transformation} to this pose stack. <br>
* The effects of this method can be reversed by a corresponding {@link PoseStack#popPose()} call.
*
* @param transformation the transformation to push
*/
default void pushTransformation(Transformation transformation)
{
final PoseStack self = self();
self.pushPose();
Vector3f trans = transformation.getTranslation();
self.translate(trans.x(), trans.y(), trans.z());
self.mulPose(transformation.getLeftRotation());
Vector3f scale = transformation.getScale();
self.scale(scale.x(), scale.y(), scale.z());
self.mulPose(transformation.getRightRotation());
}
}
@@ -12,10 +12,13 @@ import com.mojang.math.Matrix4f;
import com.mojang.math.Transformation;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
/**
* Extension interface for {@link Transformation}.
*/
// TODO - 1.20: Transformation is not client-only, move this extension outside the client package
public interface IForgeTransformation
{
private Transformation self()
@@ -37,22 +40,15 @@ public interface IForgeTransformation
* Pushes and applies this transformation to the pose stack. The effects of this method can be reversed by a
* corresponding {@link PoseStack#popPose()}.
*
* @deprecated Use {@linkplain PoseStack#pushTransformation(Transformation)}, as {@linkplain Transformation} can be present in common code.
*
* @param stack the pose stack to modify
*/
@OnlyIn(Dist.CLIENT) // TODO - 1.20: Remove in favour of client-only PoseStack extension
@Deprecated(forRemoval = true, since = "1.19.2")
default void push(PoseStack stack)
{
stack.pushPose();
Vector3f trans = self().getTranslation();
stack.translate(trans.x(), trans.y(), trans.z());
stack.mulPose(self().getLeftRotation());
Vector3f scale = self().getScale();
stack.scale(scale.x(), scale.y(), scale.z());
stack.mulPose(self().getRightRotation());
stack.pushTransformation(self());
}
/**
@@ -23,10 +23,12 @@ import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.ChunkRenderTypeSet;
import net.minecraftforge.client.RenderTypeGroup;
@@ -169,6 +171,15 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
return ConcatenatedListView.of(quadLists);
}
@Override
public @NotNull ModelData getModelData(@NotNull BlockAndTintGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull ModelData modelData)
{
var builder = Data.builder();
for (var entry : children.entrySet())
builder.with(entry.getKey(), entry.getValue().getModelData(level, pos, state, Data.resolve(modelData, entry.getKey())));
return modelData.derive().with(Data.PROPERTY, builder.build()).build();
}
@Override
public boolean useAmbientOcclusion()
{
@@ -62,9 +62,11 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
if (deprecatedLoader)
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"minecraft:elements\" instead of \"forge:elements\". This loader will be removed in 1.20.");
var rootTransform = context.getRootTransform();
if (!rootTransform.isIdentity())
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
// If there is a root transform, undo the ModelState transform, apply it, then re-apply the ModelState transform.
// This is necessary because of things like UV locking, which should only respond to the ModelState, and as such
// that is the only transform that should be applied during face bake.
var postTransform = context.getRootTransform().isIdentity() ? QuadTransformers.empty() :
QuadTransformers.applying(modelState.getRotation().compose(context.getRootTransform()).compose(modelState.getRotation().inverse()));
for (BlockElement element : elements)
{
@@ -73,6 +75,7 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
var face = element.faces.get(direction);
var sprite = spriteGetter.apply(context.getMaterial(face.texture));
var quad = BlockModel.bakeFace(element, face, sprite, direction, modelState, modelLocation);
postTransform.processInPlace(quad);
if (face.cullForDirection == null)
modelBuilder.addUnculledFace(quad);
@@ -92,7 +92,7 @@ public interface IQuadTransformer
private static BakedQuad copy(BakedQuad quad)
{
var vertices = quad.getVertices();
return new BakedQuad(Arrays.copyOf(vertices, vertices.length), quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
return new BakedQuad(Arrays.copyOf(vertices, vertices.length), quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade(), quad.hasAmbientOcclusion());
}
private static int findOffset(VertexFormatElement element)
@@ -64,7 +64,7 @@ public final class QuadTransformers {
{
int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
int normalIn = vertices[offset];
if ((normalIn >> 8) != 0)
if ((normalIn & 0x00FFFFFF) != 0) // The ignored byte is padding and may be filled with user data
{
float x = ((byte) (normalIn & 0xFF)) / 127.0f;
float y = ((byte) ((normalIn >> 8) & 0xFF)) / 127.0f;
@@ -72,12 +72,11 @@ public final class QuadTransformers {
Vector3f pos = new Vector3f(x, y, z);
transform.transformNormal(pos);
pos.normalize();
vertices[offset] = (((byte) (x * 127.0f)) & 0xFF) |
((((byte) (y * 127.0f)) & 0xFF) << 8) |
((((byte) (z * 127.0f)) & 0xFF) << 16) |
(normalIn & 0xFF000000);
vertices[offset] = (((byte) (pos.x() * 127.0f)) & 0xFF) |
((((byte) (pos.y() * 127.0f)) & 0xFF) << 8) |
((((byte) (pos.z() * 127.0f)) & 0xFF) << 16) |
(normalIn & 0xFF000000); // Restore padding, just in case
}
}
};
@@ -5,8 +5,17 @@
package net.minecraftforge.client.model.generators;
import com.google.common.base.Preconditions;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mojang.math.Quaternion;
import com.mojang.math.Transformation;
import com.mojang.math.Vector3f;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringRepresentable;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Builder for block models, does not currently provide any additional
@@ -16,9 +25,374 @@ import net.minecraftforge.common.data.ExistingFileHelper;
* @see ModelProvider
* @see ModelBuilder
*/
public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder> {
public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
{
private final RootTransformBuilder rootTransform = new RootTransformBuilder();
public BlockModelBuilder(ResourceLocation outputLocation, ExistingFileHelper existingFileHelper) {
public BlockModelBuilder(ResourceLocation outputLocation, ExistingFileHelper existingFileHelper)
{
super(outputLocation, existingFileHelper);
}
public RootTransformBuilder rootTransform()
{
return rootTransform;
}
@Override
public JsonObject toJson()
{
JsonObject json = super.toJson();
// If there were any transform properties set, add them to the output.
JsonObject transform = rootTransform.toJson();
if (transform.size() > 0)
{
json.add("transform", transform);
}
return json;
}
public class RootTransformBuilder
{
private static final Vector3f ONE = new Vector3f(1, 1, 1);
private Vector3f translation = Vector3f.ZERO;
private Quaternion leftRotation = Quaternion.ONE.copy();
private Quaternion rightRotation = Quaternion.ONE.copy();
private Vector3f scale = ONE;
private @Nullable TransformOrigin origin;
private @Nullable Vector3f originVec;
private RootTransformBuilder()
{
}
/**
* Sets the translation of the root transform.
*
* @param translation the translation
* @return this builder
* @throws NullPointerException if {@code translation} is {@code null}
*/
public RootTransformBuilder translation(Vector3f translation)
{
this.translation = Preconditions.checkNotNull(translation, "Translation must not be null");
return this;
}
/**
* Sets the translation of the root transform.
*
* @param x x translation
* @param y y translation
* @param z z translation
* @return this builder
*/
public RootTransformBuilder translation(float x, float y, float z)
{
return translation(new Vector3f(x, y, z));
}
/**
* Sets the left rotation of the root transform.
*
* @param rotation the left rotation
* @return this builder
* @throws NullPointerException if {@code rotation} is {@code null}
*/
public RootTransformBuilder rotation(Quaternion rotation)
{
this.leftRotation = Preconditions.checkNotNull(rotation, "Rotation must not be null");
return this;
}
/**
* Sets the left rotation of the root transform.
*
* @param x x rotation
* @param y y rotation
* @param z z rotation
* @param isDegrees whether the rotation is in degrees or radians
* @return this builder
*/
public RootTransformBuilder rotation(float x, float y, float z, boolean isDegrees)
{
return rotation(new Quaternion(x, y, z, isDegrees));
}
/**
* Sets the left rotation of the root transform.
*
* @param leftRotation the left rotation
* @return this builder
* @throws NullPointerException if {@code leftRotation} is {@code null}
*/
public RootTransformBuilder leftRotation(Quaternion leftRotation)
{
return rotation(leftRotation);
}
/**
* Sets the left rotation of the root transform.
*
* @param x x rotation
* @param y y rotation
* @param z z rotation
* @param isDegrees whether the rotation is in degrees or radians
* @return this builder
*/
public RootTransformBuilder leftRotation(float x, float y, float z, boolean isDegrees)
{
return leftRotation(new Quaternion(x, y, z, isDegrees));
}
/**
* Sets the right rotation of the root transform.
*
* @param rightRotation the right rotation
* @return this builder
* @throws NullPointerException if {@code rightRotation} is {@code null}
*/
public RootTransformBuilder rightRotation(Quaternion rightRotation)
{
this.rightRotation = Preconditions.checkNotNull(rightRotation, "Rotation must not be null");
return this;
}
/**
* Sets the right rotation of the root transform.
*
* @param x x rotation
* @param y y rotation
* @param z z rotation
* @param isDegrees whether the rotation is in degrees or radians
* @return this builder
*/
public RootTransformBuilder rightRotation(float x, float y, float z, boolean isDegrees)
{
return rightRotation(new Quaternion(x, y, z, isDegrees));
}
/**
* Sets the right rotation of the root transform.
*
* @param postRotation the right rotation
* @return this builder
* @throws NullPointerException if {@code rightRotation} is {@code null}
*/
public RootTransformBuilder postRotation(Quaternion postRotation)
{
return rightRotation(postRotation);
}
/**
* Sets the right rotation of the root transform.
*
* @param x x rotation
* @param y y rotation
* @param z z rotation
* @param isDegrees whether the rotation is in degrees or radians
* @return this builder
*/
public RootTransformBuilder postRotation(float x, float y, float z, boolean isDegrees)
{
return postRotation(new Quaternion(x, y, z, isDegrees));
}
/**
* Sets the scale of the root transform.
*
* @param scale the scale
* @return this builder
* @throws NullPointerException if {@code scale} is {@code null}
*/
public RootTransformBuilder scale(float scale)
{
return scale(new Vector3f(scale, scale, scale));
}
/**
* Sets the scale of the root transform.
*
* @param xScale x scale
* @param yScale y scale
* @param zScale z scale
* @return this builder
*/
public RootTransformBuilder scale(float xScale, float yScale, float zScale)
{
return scale(new Vector3f(xScale, yScale, zScale));
}
/**
* Sets the scale of the root transform.
*
* @param scale the scale vector
* @return this builder
* @throws NullPointerException if {@code scale} is {@code null}
*/
public RootTransformBuilder scale(Vector3f scale)
{
this.scale = Preconditions.checkNotNull(scale, "Scale must not be null");
return this;
}
/**
* Sets the root transform.
*
* @param transformation the transformation to use
* @return this builder
* @throws NullPointerException if {@code transformation} is {@code null}
*/
public RootTransformBuilder transform(Transformation transformation)
{
Preconditions.checkNotNull(transformation, "Transformation must not be null");
this.translation = transformation.getTranslation();
this.leftRotation = transformation.getLeftRotation();
this.rightRotation = transformation.getRightRotation();
this.scale = transformation.getScale();
return this;
}
/**
* Sets the origin of the root transform.
*
* @param origin the origin vector
* @return this builder
* @throws NullPointerException if {@code origin} is {@code null}
*/
public RootTransformBuilder origin(Vector3f origin)
{
this.originVec = Preconditions.checkNotNull(origin, "Origin must not be null");
this.origin = null;
return this;
}
/**
* Sets the origin of the root transform.
*
* @param origin the origin name
* @return this builder
* @throws NullPointerException if {@code origin} is {@code null}
* @throws IllegalArgumentException if {@code origin} is not {@code center}, {@code corner} or {@code opposing-corner}
*/
public RootTransformBuilder origin(TransformOrigin origin)
{
this.origin = Preconditions.checkNotNull(origin, "Origin must not be null");
this.originVec = null;
return this;
}
/**
* Finish configuring the parent builder
* @return the parent block model builder
*/
public BlockModelBuilder end()
{
return BlockModelBuilder.this;
}
public JsonObject toJson() {
// Write the transform to an object
JsonObject transform = new JsonObject();
if (!translation.equals(Vector3f.ZERO))
{
transform.add("translation", writeVec3(translation));
}
if (!scale.equals(ONE))
{
transform.add("scale", writeVec3(scale));
}
if (!leftRotation.equals(Quaternion.ONE))
{
transform.add("rotation", writeQuaternion(leftRotation));
}
if (!rightRotation.equals(Quaternion.ONE))
{
transform.add("post_rotation", writeQuaternion(rightRotation));
}
if (origin != null)
{
transform.addProperty("origin", origin.getSerializedName());
}
else if (originVec != null && !originVec.equals(Vector3f.ZERO))
{
transform.add("origin", writeVec3(originVec));
}
return transform;
}
public enum TransformOrigin implements StringRepresentable
{
CENTER(new Vector3f(.5f, .5f, .5f), "center"),
CORNER(Vector3f.ZERO, "corner"),
OPPOSING_CORNER(ONE, "opposing-corner");
private final Vector3f vec;
private final String name;
TransformOrigin(Vector3f vec, String name)
{
this.vec = vec;
this.name = name;
}
public Vector3f getVector()
{
return vec;
}
@Override
@NotNull
public String getSerializedName()
{
return name;
}
public static @Nullable TransformOrigin fromString(String originName)
{
if (CENTER.getSerializedName().equals(originName))
{
return CENTER;
}
if (CORNER.getSerializedName().equals(originName))
{
return CORNER;
}
if (OPPOSING_CORNER.getSerializedName().equals(originName))
{
return OPPOSING_CORNER;
}
return null;
}
}
private JsonArray writeVec3(Vector3f vector)
{
JsonArray array = new JsonArray();
array.add(vector.x());
array.add(vector.y());
array.add(vector.z());
return array;
}
private JsonArray writeQuaternion(Quaternion quaternion)
{
JsonArray array = new JsonArray();
array.add(quaternion.i());
array.add(quaternion.j());
array.add(quaternion.k());
array.add(quaternion.r());
return array;
}
}
}
@@ -320,6 +320,9 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
if (face.emissivity > 0) {
faceObj.addProperty("emissivity", face.emissivity);
}
if (!face.hasAmbientOcclusion) {
faceObj.addProperty("ambientocclusion", face.hasAmbientOcclusion);
}
faces.add(dir.getSerializedName(), faceObj);
}
if (!part.faces.isEmpty()) {
@@ -517,6 +520,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
private float[] uvs;
private FaceRotation rotation = FaceRotation.ZERO;
private int emissivity = 0;
private boolean hasAmbientOcclusion = true;
FaceBuilder(Direction dir) {
// param unused for functional match
@@ -583,11 +587,22 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
return emissivity(15);
}
/**
* Set the ambient occlusion of the face.
*
* @param ao the ambient occlusion
* @return this builder
*/
public FaceBuilder ao(boolean ao) {
this.hasAmbientOcclusion = ao;
return this;
}
BlockElementFace build() {
if (this.texture == null) {
throw new IllegalStateException("A model face must have a texture");
}
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), emissivity);
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), emissivity, hasAmbientOcclusion);
}
public ElementBuilder end() { return ElementBuilder.this; }
@@ -19,12 +19,13 @@ import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.BuiltInModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.RenderTypeGroup;
import net.minecraftforge.client.model.ElementsModel;
import net.minecraftforge.client.model.IModelBuilder;
import net.minecraftforge.client.model.SimpleModelState;
import org.jetbrains.annotations.ApiStatus;
@@ -98,17 +99,30 @@ public class UnbakedGeometryHelper
if (customModel != null)
return customModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
Transformation rootTransform = blockModel.customData.getRootTransform();
if (!rootTransform.isIdentity())
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
// Handle vanilla item models here, since vanilla has a shortcut for them
if (blockModel.getRootModel() == ModelBakery.GENERATION_MARKER)
return ITEM_MODEL_GENERATOR.generateBlockModel(spriteGetter, blockModel).bake(modelBakery, blockModel, spriteGetter, modelState, modelLocation, guiLight3d);
var renderTypeHint = blockModel.customData.getRenderTypeHint();
var renderTypes = renderTypeHint != null ? blockModel.customData.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;
return blockModel.bakeVanilla(modelBakery, owner, spriteGetter, modelState, modelLocation, guiLight3d, renderTypes);
return bakeVanilla(blockModel, modelBakery, owner, spriteGetter, modelState, modelLocation);
}
/**
* Helper for baking vanilla {@link BlockModel} instances.
*
* @deprecated Merge into the method above in 1.20 once the call from {@link BlockModel} is gone.
*/
@ApiStatus.Internal
@Deprecated(forRemoval = true, since = "1.19.2")
public static BakedModel bakeVanilla(BlockModel blockModel, ModelBakery modelBakery, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
{
if (blockModel.getRootModel() == ModelBakery.BLOCK_ENTITY_MARKER)
{
var particleSprite = spriteGetter.apply(blockModel.getMaterial("particle"));
return new BuiltInModel(blockModel.getTransforms(), blockModel.getOverrides(modelBakery, owner, spriteGetter), particleSprite, blockModel.getGuiLight().lightLikeBlock());
}
var elementsModel = new ElementsModel(blockModel.getElements());
return elementsModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
}
/**
@@ -7,6 +7,7 @@ package net.minecraftforge.client.model.lighting;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
@@ -67,8 +68,11 @@ public class ForgeModelBlockRenderer extends ModelBlockRenderer
public static boolean render(VertexConsumer vertexConsumer, QuadLighter lighter, BlockAndTintGetter level, BakedModel model, BlockState state, BlockPos pos, PoseStack poseStack, boolean checkSides, RandomSource rand, long seed, int packedOverlay, ModelData modelData, RenderType renderType)
{
ForgeModelBlockRenderer renderer = (ForgeModelBlockRenderer)Minecraft.getInstance().getBlockRenderer().getModelRenderer();
var pose = poseStack.last();
var empty = true;
var smoothLighter = lighter instanceof SmoothQuadLighter;
QuadLighter flatLighter = null;
rand.setSeed(seed);
List<BakedQuad> quads = model.getQuads(state, null, rand, modelData, renderType);
@@ -78,7 +82,19 @@ public class ForgeModelBlockRenderer extends ModelBlockRenderer
lighter.setup(level, pos, state);
for (BakedQuad quad : quads)
{
lighter.process(vertexConsumer, pose, quad, packedOverlay);
if (smoothLighter && !quad.hasAmbientOcclusion())
{
if (flatLighter == null)
{
flatLighter = renderer.flatLighter.get();
flatLighter.setup(level, pos, state);
}
flatLighter.process(vertexConsumer, pose, quad, packedOverlay);
}
else
{
lighter.process(vertexConsumer, pose, quad, packedOverlay);
}
}
}
@@ -99,11 +115,25 @@ public class ForgeModelBlockRenderer extends ModelBlockRenderer
}
for (BakedQuad quad : quads)
{
lighter.process(vertexConsumer, pose, quad, packedOverlay);
if (smoothLighter && !quad.hasAmbientOcclusion())
{
if (flatLighter == null)
{
flatLighter = renderer.flatLighter.get();
flatLighter.setup(level, pos, state);
}
flatLighter.process(vertexConsumer, pose, quad, packedOverlay);
}
else
{
lighter.process(vertexConsumer, pose, quad, packedOverlay);
}
}
}
}
lighter.reset();
if (flatLighter != null)
flatLighter.reset();
return !empty;
}
}
@@ -68,7 +68,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
new Vec2(1, 0),
};
private final Map<String, ModelGroup> parts = Maps.newHashMap();
private final Map<String, ModelGroup> parts = Maps.newLinkedHashMap();
private final Set<String> rootComponentNames = Collections.unmodifiableSet(parts.keySet());
private Set<String> allComponentNames;
@@ -402,8 +402,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
faceNormal = abs;
}
var quad = new BakedQuad[1];
var quadBaker = new QuadBakingVertexConsumer(q -> quad[0] = q);
var quadBaker = new QuadBakingVertexConsumer.Buffered();
quadBaker.setSprite(texture);
quadBaker.setTintIndex(tintIndex);
@@ -516,7 +515,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
}
}
return Pair.of(quad[0], cull);
return Pair.of(quadBaker.getQuad(), cull);
}
public CompositeRenderable bakeRenderable(IGeometryBakingContext configuration)
@@ -582,7 +581,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
public class ModelGroup extends ModelObject
{
final Map<String, ModelObject> parts = Maps.newHashMap();
final Map<String, ModelObject> parts = Maps.newLinkedHashMap();
ModelGroup(String name)
{
@@ -652,9 +651,11 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
int tintIndex = mat.diffuseTintIndex;
Vector4f colorTint = mat.diffuseColor;
var rootTransform = owner.getRootTransform();
var transform = rootTransform.isIdentity() ? modelTransform.getRotation() : modelTransform.getRotation().compose(rootTransform);
for (int[][] face : faces)
{
Pair<BakedQuad, Direction> quad = makeQuad(face, tintIndex, colorTint, mat.ambientColor, texture, modelTransform.getRotation());
Pair<BakedQuad, Direction> quad = makeQuad(face, tintIndex, colorTint, mat.ambientColor, texture, transform);
if (quad.getRight() == null)
modelBuilder.addUnculledFace(quad.getLeft());
else
@@ -5,6 +5,7 @@
package net.minecraftforge.client.model.pipeline;
import com.google.common.base.Preconditions;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormatElement;
@@ -37,13 +38,14 @@ public class QuadBakingVertexConsumer implements VertexConsumer
private final Consumer<BakedQuad> quadConsumer;
private int vertexIndex = 0;
int vertexIndex = 0;
private int[] quadData = new int[QUAD_DATA_SIZE];
private int tintIndex;
private Direction direction = Direction.DOWN;
private TextureAtlasSprite sprite = UnitTextureAtlasSprite.INSTANCE;
private boolean shade;
private boolean hasAmbientOcclusion;
public QuadBakingVertexConsumer(Consumer<BakedQuad> quadConsumer)
{
@@ -127,7 +129,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
if (++vertexIndex != 4)
return;
// We have a full quad, pass it to the consumer and reset
quadConsumer.accept(new BakedQuad(quadData, tintIndex, direction, sprite, shade));
quadConsumer.accept(new BakedQuad(quadData, tintIndex, direction, sprite, shade, hasAmbientOcclusion));
vertexIndex = 0;
quadData = new int[QUAD_DATA_SIZE];
}
@@ -161,4 +163,32 @@ public class QuadBakingVertexConsumer implements VertexConsumer
{
this.shade = shade;
}
public void setHasAmbientOcclusion(boolean hasAmbientOcclusion)
{
this.hasAmbientOcclusion = hasAmbientOcclusion;
}
public static class Buffered extends QuadBakingVertexConsumer
{
private final BakedQuad[] output;
public Buffered()
{
this(new BakedQuad[1]);
}
private Buffered(BakedQuad[] output)
{
super(q -> output[0] = q);
this.output = output;
}
public BakedQuad getQuad()
{
var quad = Preconditions.checkNotNull(output[0], "No quad has been emitted. Vertices in buffer: " + vertexIndex);
output[0] = null;
return quad;
}
}
}
@@ -23,7 +23,7 @@ public enum KeyModifier {
int keyCode = key.getValue();
if (Minecraft.ON_OSX)
{
return keyCode == GLFW.GLFW_KEY_LEFT_ALT || keyCode == GLFW.GLFW_KEY_RIGHT_ALT;
return keyCode == GLFW.GLFW_KEY_LEFT_SUPER || keyCode == GLFW.GLFW_KEY_RIGHT_SUPER;
}
else
{
@@ -83,28 +83,31 @@ public class ForgeConfig {
* General configuration that doesn't need to be synchronized but needs to be available before server startup
*/
public static class Common {
@Deprecated(since = "1.19.2", forRemoval = true)
public final BooleanValue cachePackAccess;
@Deprecated(since = "1.19.2", forRemoval = true)
public final BooleanValue indexVanillaPackCachesOnThread;
@Deprecated(since = "1.19.2", forRemoval = true)
public final BooleanValue indexModPackCachesOnThread;
Common(ForgeConfigSpec.Builder builder) {
builder.comment("General configuration settings")
builder.comment("[DEPRECATED / NO EFFECT]: General configuration settings")
.push("general");
cachePackAccess = builder
.comment("Set this to true to cache resource listings in resource and data packs")
.comment("[DEPRECATED / NO EFFECT] [NOW IN RESOURCE-CACHING CONFIG]: Set this to true to cache resource listings in resource and data packs")
.translation("forge.configgui.cachePackAccess")
.worldRestart()
.define("cachePackAccess", true);
indexVanillaPackCachesOnThread = builder
.comment("Set this to true to index vanilla resource and data packs on thread")
.comment("[DEPRECATED / NO EFFECT] [NOW IN RESOURCE-CACHING CONFIG]: Set this to true to index vanilla resource and data packs on thread")
.translation("forge.configgui.indexVanillaPackCachesOnThread")
.worldRestart()
.define("indexVanillaPackCachesOnThread", false);
indexModPackCachesOnThread = builder
.comment("Set this to true to index mod resource and data packs on thread")
.comment("[DEPRECATED / NO EFFECT] [NOW IN RESOURCE-CACHING CONFIG]: Set this to true to index mod resource and data packs on thread")
.translation("forge.configgui.indexModPackCachesOnThread")
.worldRestart()
.define("indexModPackCachesOnThread", false);
@@ -44,8 +44,7 @@ import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.ObjectArrays;
import org.jetbrains.annotations.NotNull;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
/*
@@ -62,6 +61,8 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
private boolean isCorrecting = false;
private static final Logger LOGGER = LogManager.getLogger();
private ForgeConfigSpec(UnmodifiableConfig storage, UnmodifiableConfig values, Map<List<String>, String> levelComments, Map<List<String>, String> levelTranslationKeys) {
super(storage);
this.values = values;
@@ -81,12 +82,12 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
this.childConfig = config;
if (config != null && !isCorrect(config)) {
String configName = config instanceof FileConfig ? ((FileConfig) config).getNioPath().toString() : config.toString();
LogManager.getLogger().warn(CORE, "Configuration file {} is not correct. Correcting", configName);
LOGGER.warn(CORE, "Configuration file {} is not correct. Correcting", configName);
correct(config,
(action, path, incorrectValue, correctedValue) ->
LogManager.getLogger().warn(CORE, "Incorrect key {} was corrected from {} to its default, {}. {}", DOT_JOINER.join( path ), incorrectValue, correctedValue, incorrectValue == correctedValue ? "This seems to be an error." : ""),
LOGGER.warn(CORE, "Incorrect key {} was corrected from {} to its default, {}. {}", DOT_JOINER.join( path ), incorrectValue, correctedValue, incorrectValue == correctedValue ? "This seems to be an error." : ""),
(action, path, incorrectValue, correctedValue) ->
LogManager.getLogger().debug(CORE, "The comment on key {} does not match the spec. This may create a backup.", DOT_JOINER.join( path )));
LOGGER.debug(CORE, "The comment on key {} does not match the spec. This may create a backup.", DOT_JOINER.join( path )));
if (config instanceof FileConfig) {
((FileConfig) config).save();
@@ -265,12 +266,9 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
private boolean stringsMatchIgnoringNewlines(@Nullable Object obj1, @Nullable Object obj2)
{
if(obj1 instanceof String && obj2 instanceof String)
if (obj1 instanceof String string1 && obj2 instanceof String string2)
{
String string1 = (String) obj1;
String string2 = (String) obj2;
if(string1.length() > 0 && string2.length() > 0)
if (string1.length() > 0 && string2.length() > 0)
{
return string1.replaceAll("\r\n", "\n")
.equals(string2.replaceAll("\r\n", "\n"));
@@ -289,7 +287,6 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
private Map<List<String>, String> levelTranslationKeys = new HashMap<>();
private List<String> currentPath = new ArrayList<>();
private List<ConfigValue<?>> values = new ArrayList<>();
private boolean hasInvalidComment = false;
//Object
public <T> ConfigValue<T> define(String path, T defaultValue) {
@@ -313,7 +310,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
}
public <T> ConfigValue<T> define(List<String> path, Supplier<T> defaultSupplier, Predicate<Object> validator, Class<?> clazz) {
context.setClazz(clazz);
return define(path, new ValueSpec(defaultSupplier, validator, context), defaultSupplier);
return define(path, new ValueSpec(defaultSupplier, validator, context, path), defaultSupplier);
}
public <T> ConfigValue<T> define(List<String> path, ValueSpec value, Supplier<T> defaultSupplier) { // This is the root where everything at the end of the day ends up.
if (!currentPath.isEmpty()) {
@@ -323,7 +320,6 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
path = tmp;
}
storage.set(path, value);
checkComment(path);
context = new BuilderContext();
return new ConfigValue<>(this, path, defaultSupplier);
}
@@ -339,7 +335,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public <V extends Comparable<? super V>> ConfigValue<V> defineInRange(List<String> path, Supplier<V> defaultSupplier, V min, V max, Class<V> clazz) {
Range<V> range = new Range<>(clazz, min, max);
context.setRange(range);
context.setComment(ObjectArrays.concat(context.getComment(), "Range: " + range.toString()));
comment("Range: " + range.toString());
if (min.compareTo(max) > 0)
throw new IllegalArgumentException("Range min most be less then max.");
return define(path, defaultSupplier, range);
@@ -367,17 +363,17 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
}
public <T> ConfigValue<List<? extends T>> defineList(List<String> path, Supplier<List<? extends T>> defaultSupplier, Predicate<Object> elementValidator) {
context.setClazz(List.class);
return define(path, new ValueSpec(defaultSupplier, x -> x instanceof List && ((List<?>) x).stream().allMatch( elementValidator ), context) {
return define(path, new ValueSpec(defaultSupplier, x -> x instanceof List && ((List<?>) x).stream().allMatch( elementValidator ), context, path) {
@Override
public Object correct(Object value) {
if (value == null || !(value instanceof List) || ((List<?>)value).isEmpty()) {
LogManager.getLogger().debug(CORE, "List on key {} is deemed to need correction. It is null, not a list, or an empty list. Modders, consider defineListAllowEmpty?", path.get(path.size() - 1));
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It is null, not a list, or an empty list. Modders, consider defineListAllowEmpty?", path.get(path.size() - 1));
return getDefault();
}
List<?> list = Lists.newArrayList((List<?>) value);
list.removeIf(elementValidator.negate());
if (list.isEmpty()) {
LogManager.getLogger().debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
return getDefault();
}
return list;
@@ -387,17 +383,17 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public <T> ConfigValue<List<? extends T>> defineListAllowEmpty(List<String> path, Supplier<List<? extends T>> defaultSupplier, Predicate<Object> elementValidator) {
context.setClazz(List.class);
return define(path, new ValueSpec(defaultSupplier, x -> x instanceof List && ((List<?>) x).stream().allMatch( elementValidator ), context) {
return define(path, new ValueSpec(defaultSupplier, x -> x instanceof List && ((List<?>) x).stream().allMatch( elementValidator ), context, path) {
@Override
public Object correct(Object value) {
if (value == null || !(value instanceof List)) {
LogManager.getLogger().debug(CORE, "List on key {} is deemed to need correction, as it is null or not a list.", path.get(path.size() - 1));
LOGGER.debug(CORE, "List on key {} is deemed to need correction, as it is null or not a list.", path.get(path.size() - 1));
return getDefault();
}
List<?> list = Lists.newArrayList((List<?>) value);
list.removeIf(elementValidator.negate());
if (list.isEmpty()) {
LogManager.getLogger().debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
return getDefault();
}
return list;
@@ -482,8 +478,8 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public <V extends Enum<V>> EnumValue<V> defineEnum(List<String> path, Supplier<V> defaultSupplier, EnumGetMethod converter, Predicate<Object> validator, Class<V> clazz) {
context.setClazz(clazz);
V[] allowedValues = clazz.getEnumConstants();
context.setComment(ObjectArrays.concat(context.getComment(), "Allowed Values: " + Arrays.stream(allowedValues).filter(validator).map(Enum::name).collect(Collectors.joining(", "))));
return new EnumValue<V>(this, define(path, new ValueSpec(defaultSupplier, validator, context), defaultSupplier).getPath(), defaultSupplier, converter, clazz);
comment("Allowed Values: " + Arrays.stream(allowedValues).filter(validator).map(Enum::name).collect(Collectors.joining(", ")));
return new EnumValue<V>(this, define(path, new ValueSpec(defaultSupplier, validator, context, path), defaultSupplier).getPath(), defaultSupplier, converter, clazz);
}
//boolean
@@ -547,23 +543,19 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public Builder comment(String comment)
{
hasInvalidComment = comment == null || comment.isEmpty();
if (hasInvalidComment)
{
comment = "No comment";
}
context.setComment(comment);
context.addComment(comment);
return this;
}
public Builder comment(String... comment)
{
hasInvalidComment = comment == null || comment.length < 1 || (comment.length == 1 && comment[0].isEmpty());
if (hasInvalidComment)
{
comment = new String[] {"No comment"};
}
// Iterate list first, to throw meaningful errors
// Don't add any comments until we make sure there is no nulls
for (int i = 0; i < comment.length; i++)
Preconditions.checkNotNull(comment[i], "Comment string at " + i + " is null.");
for (String s : comment)
context.addComment(s);
context.setComment(comment);
return this;
}
@@ -585,10 +577,9 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public Builder push(List<String> path) {
currentPath.addAll(path);
checkComment(currentPath);
if (context.hasComment()) {
levelComments.put(new ArrayList<String>(currentPath), context.buildComment());
context.setComment(); // Set to empty
levelComments.put(new ArrayList<>(currentPath), context.buildComment(path));
context.clearComment(); // Set to empty
}
if (context.getTranslationKey() != null) {
levelTranslationKeys.put(new ArrayList<String>(currentPath), context.getTranslationKey());
@@ -626,19 +617,6 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
return ret;
}
private void checkComment(List<String> path)
{
if (hasInvalidComment)
{
hasInvalidComment = false;
if (!FMLEnvironment.production)
{
LogManager.getLogger().error(CORE, "Null comment for config option {}, this is invalid and may be disallowed in the future.",
DOT_JOINER.join(path));
}
}
}
public interface BuilderConsumer {
void accept(Builder builder);
}
@@ -646,20 +624,38 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
private static class BuilderContext
{
private @NotNull String[] comment = new String[0];
private final List<String> comment = new LinkedList<>();
private String langKey;
private Range<?> range;
private boolean worldRestart = false;
private Class<?> clazz;
public void setComment(String... value)
public void addComment(String value)
{
validate(value == null, "Passed in null value for comment");
this.comment = value;
// Don't use `validate` because it throws IllegalStateException, not NullPointerException
Preconditions.checkNotNull(value, "Passed in null value for comment");
comment.add(value);
}
public void clearComment() { comment.clear(); }
public boolean hasComment() { return this.comment.size() > 0; }
public String buildComment() { return buildComment(List.of("unknown", "unknown")); }
public String buildComment(final List<String> path)
{
if (comment.stream().allMatch(String::isBlank))
{
if (FMLEnvironment.production)
LOGGER.warn(CORE, "Detected a comment that is all whitespace for config option {}, which causes obscure bugs in Forge's config system and will cause a crash in the future. Please report this to the mod author.",
DOT_JOINER.join(path));
else
throw new IllegalStateException("Can not build comment for config option " + DOT_JOINER.join(path) + " as it comprises entirely of blank lines/whitespace. This is not allowed as it causes a \"constantly correcting config\" bug with NightConfig in Forge's config system.");
return "A developer of this mod has defined this config option with a blank comment, which causes obscure bugs in Forge's config system and will cause a crash in the future. Please report this to the mod author.";
}
return LINE_JOINER.join(comment);
}
public boolean hasComment() { return this.comment.length > 0; }
public String[] getComment() { return this.comment; }
public String buildComment() { return LINE_JOINER.join(comment); }
public void setTranslationKey(String value) { this.langKey = value; }
public String getTranslationKey() { return this.langKey; }
public <V extends Comparable<? super V>> void setRange(Range<V> value)
@@ -726,7 +722,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
boolean result = ((Number)min).doubleValue() <= n.doubleValue() && n.doubleValue() <= ((Number)max).doubleValue();
if(!result)
{
LogManager.getLogger().debug(CORE, "Range value {} is not within its bounds {}-{}", n.doubleValue(), ((Number)min).doubleValue(), ((Number)max).doubleValue());
LOGGER.debug(CORE, "Range value {} is not within its bounds {}-{}", n.doubleValue(), ((Number)min).doubleValue(), ((Number)max).doubleValue());
}
return result;
}
@@ -736,7 +732,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
boolean result = c.compareTo(min) >= 0 && c.compareTo(max) <= 0;
if(!result)
{
LogManager.getLogger().debug(CORE, "Range value {} is not within its bounds {}-{}", c, min, max);
LOGGER.debug(CORE, "Range value {} is not within its bounds {}-{}", c, min, max);
}
return result;
}
@@ -776,14 +772,13 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
private final Class<?> clazz;
private final Supplier<?> supplier;
private final Predicate<Object> validator;
private Object _default = null;
private ValueSpec(Supplier<?> supplier, Predicate<Object> validator, BuilderContext context)
private ValueSpec(Supplier<?> supplier, Predicate<Object> validator, BuilderContext context, List<String> path)
{
Objects.requireNonNull(supplier, "Default supplier can not be null");
Objects.requireNonNull(validator, "Validator can not be null");
this.comment = context.hasComment() ? context.buildComment() : null;
this.comment = context.hasComment() ? context.buildComment(path) : null;
this.langKey = context.getTranslationKey();
this.range = context.getRange();
this.worldRestart = context.needsWorldRestart();
@@ -801,12 +796,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
public boolean test(Object value) { return validator.test(value); }
public Object correct(Object value) { return range == null ? getDefault() : range.correct(value, getDefault()); }
public Object getDefault()
{
if (_default == null)
_default = supplier.get();
return _default;
}
public Object getDefault() { return supplier.get(); }
}
public static class ConfigValue<T> implements Supplier<T>
Loaded 100 of 198 files, more files were not shown because too many files have changed in this diff. Show more