Compare commits

...
67 Commits
Author SHA1 Message Date
LexManos 658e614dc1 1.19.4 Recommended Build 2023-06-07 12:08:15 -07:00
Apex 9abfcbc90b Add method to GatherDataEvent to obtain collection of all input paths. (#9499) 2023-05-29 13:47:21 -07:00
Dennis C 6ee20899bf Log error when Sheets is class-loaded before registration is completed (#9475) 2023-05-29 13:47:04 -07:00
Dennis C 42115d37d6 [1.19.x] Re-implement RenderTooltipEvent.Color (#9497)
* Reimplement RenderTooltipEvent.Color

* Formatting, comments, EXC

* Deprecate instead of replacing
2023-05-16 12:24:27 +02:00
Joseph B 8abe9b6b0c Add API for registering custom world preset editors (#9436) 2023-05-14 15:53:34 -05:00
embeddedt fc91dfd1d1 Remove unneeded extra reload of datapacks on world creation screen (#9454) 2023-05-14 15:52:57 -05:00
SizableShrimp 8cd6f2d237 Bump ASM to 9.5 2023-05-14 15:50:07 -05:00
SizableShrimp f1702495ef Fix crash when running server from root directory
Fixes #9498
2023-05-14 15:26:24 -05:00
Dennis C 2ab2ced589 Fix root transform matrix format, allow using all four root transform formats (#9496) 2023-05-12 11:20:01 -07:00
Apex c8f9e59fef Add missing AT lines to allow registering custom game rule boolean/integer types (#9489) 2023-05-10 09:27:10 -07:00
Brennan WardandBrennan Ward 9a25527a54 [1.19.x] Fix SaplingGrowTreeEvent#setFeature being ignored in FungusBlock (#9485)
Co-authored-by: Brennan Ward <[email protected]>
2023-05-05 23:09:13 -05:00
SizableShrimp ad6d11671e Restore AccessibilityOnboardingScreen
Fixes #9488
2023-05-05 23:07:49 -05:00
Brennan Ward 3c93cd414d Update documentation on FinalizeSpawn (#9467) 2023-05-05 10:26:41 -07:00
DBotThePony 2c243626f6 Fix fluids without sound event causing exception in tryFillContainer and tryEmptyContainer (#9445) 2023-05-05 10:26:28 -07:00
Technici4n ae05036bb3 Make FakePlayerFactory respect the given ServerLevel (#9479) 2023-05-05 10:03:55 -07:00
Dennis C 3de22ffba3 Collect and log exceptions occurring in DeferredWorkQueue tasks (#9449) 2023-05-04 16:43:34 -07:00
matyrobbrt e1bf07dece Fix NamespacedWrapper#wrapAsHolder (#9450) 2023-05-04 16:42:02 -07:00
RealMangoRage 0ae63b0b07 Fixes ChatScreen calling .setScreen (#9443)
Fix test compile failures also.
2023-04-30 22:57:52 +01:00
matyrobbrt d4f211b815 Determine the Forge version the PR was built against when running PR compat checks (#9374) 2023-04-24 10:59:56 -07:00
SizableShrimp 393b28d7bb Add buildscript test to error on deprecated members that should of been removed. (#9460) 2023-04-24 10:59:37 -07:00
sciwhiz12 47c807c0e3 Remove erroneous brace patch in Inventory (#9462)
Fixes #9459
2023-04-23 13:24:20 +01:00
Dennis C b398f52a7f [1.19.4] Move root transform builder to ModelBuilder to allow use in ItemModelBuilder (#9456) 2023-04-20 09:27:30 +02:00
SizableShrimp f2aeeeb1fe Fix forge grindstone hooks allowing stacks of non-stackable items (#9457) 2023-04-20 00:19:35 -07:00
matyrobbrt dcef406df8 [1.19.4] Fix FMLOnly (#9415) 2023-04-18 16:46:04 +01:00
Dennis C 01846c729a Fix ItemLayerModel erroneously adding particle texture to layer texture list (#9441) 2023-04-07 08:16:17 +02:00
LexManos e6aaaff3f3 Temporary fix for Canceling ProjectileImpactEvents of Piercing ammo.
Event needs to be re-worked to have finer control. #9370
2023-04-05 11:16:39 -07:00
Brennan Ward d4836bc769 Fix dummy air blocks not being marked as air (#9440) 2023-04-03 15:04:34 -07:00
matyrobbrt b5655b0ddc Add support for splitting the login packet (#9367)
It contains full copies of data registries and can easily surpass vanilla's limits
2023-03-30 15:59:01 -07:00
Brennan Ward d75d333e13 Remove Attack Range and Reach Distance and add Block Reach and Entity Reach (#9361) 2023-03-29 18:53:41 -07:00
ChampionAsh5357 f5e16aa353 Add default bucket sounds for milk (#9432) 2023-03-29 18:48:29 -07:00
LexManos 4e5eecac12 Deprecate Item.onUsingTick, as vanilla provides the same function in Item.onUseTick now. Closes #9342 2023-03-29 18:46:00 -07:00
Brennan Ward a111073181 Fix ScreenEvent.Init.[Pre/Post] not working correctly (#9431) 2023-03-29 18:18:38 -07:00
LexManos a05f555ab8 Allow FenceGateBlock to be used without a WoodType. Closes #9392 2023-03-29 17:59:51 -07:00
LexManos df3db236e5 Deprecate duplicate tool tags that vanilla added in 1.19.4
We will maintain a seperate 'tools' tag until Mojang adds all relevent tool tags.
Closes #9393
2023-03-29 17:59:50 -07:00
LexManos 71b115c8fe Fix BlockEvent.Break not using ItemStack enchantment hooks. 2023-03-29 17:59:49 -07:00
LexManos 3e1b01af2c Move Block.onCatchFire to above block removal to allow usage of BlockEntity data. Closes #9400 2023-03-29 17:59:48 -07:00
Brennan Ward 1ab0685d04 Fix FinalizeSpawn not blocking spawns during worldgen (#9420) 2023-03-29 16:10:59 -07:00
LexManos 5c44992d1c Fixed issue with MutableHashedLinkedMap when removing multiple sequential entries in the middle of the map.
Added Unit tests for MutableHashLinkedMap
Added support for removing using the iterator
Added concurrent modification detection to the iterator
Added default constructor with basic hashing strategy.

Closes #9426
2023-03-29 15:49:49 -07:00
TelepathicGrunt d448ffd539 Loosen access for BucketItem's canBlockContainFluid (#9421) 2023-03-28 13:34:10 -07:00
ChampionAsh5357 9f895a79f2 Update and Regenerate Datapacks (#9419)
Add generation for pack.mcmeta
2023-03-28 13:33:59 -07:00
Paint_Ninja 6e1de81ff5 Restore ability to change message in ClientChatEvent (#9377) 2023-03-27 14:35:05 -07:00
sciwhiz12 b493a63fb6 Remove duplicate line in FoodData patch (#9424)
The line was accidentally duplicated in the 1.19.4 update and patching
process.

Fixes #9422
2023-03-27 12:51:53 -07:00
Joseph B ae65f5a255 Rename RegisterParticleProviderEvent's register methods to describe what kind of particle providers they register (deprecating old methods to avoid breaking) and minor docs tweaks (#9388) 2023-03-25 19:57:39 -07:00
noeppi_noeppi bb49b9e6dc Update pack versions (#9414) 2023-03-24 13:17:22 -07:00
Brennan Ward 2815e69407 [1.19.4] Revamp and fix spawn events (#9133) 2023-03-23 18:29:06 +00:00
Exopandora b33efc0727 [1.19.4] Replace blitOffset parameter with PoseStack in IItemDecorator (#9409)
* Replace blitOffset with PoseStack in IItemDecorator

* Circumvent breaking changes

* Fix blitOffset type
2023-03-22 11:11:01 +01:00
Dennis C 434c1ec4f8 Fix JSON model root transforms (#9410) 2023-03-22 11:09:41 +01:00
Dennis C c58d922324 Fix tossed items not being able to be picked up by other players. Closes #9412 (#9404) 2023-03-21 19:15:04 -07:00
Dennis C 331374dc7a Fix infinite BE render bounds failing frustum intersection test. Closes #9321 (#9407) 2023-03-21 12:16:49 -07:00
matyrobbrt c18eb23259 Make ForgeSlider use the new vanilla texture (#9406) 2023-03-20 14:16:35 -07:00
J.T. McQuigg d0e2242043 Add BlockSetType#register to accesstransformer.cfg (#9386) 2023-03-20 14:16:18 -07:00
Dennis C 684d36201f Add option to completely hide a crash-callable depending on a runtime value (#9372) 2023-03-20 14:15:59 -07:00
Jason 7b8ca60d32 Add isNewChunk to ChunkEvent.Load (#9369) 2023-03-20 14:15:33 -07:00
sciwhiz12 576ff81856 Remove DistExecutor calls in PistonEventTest (#9348) 2023-03-20 14:14:21 -07:00
sciwhiz12 73e68c9322 Fix hardcoded precipitation in ClimateSettingsBuilder (#9402)
This effectively caused all biomes to have precipitation, such as
minecraft:desert.

Fixes #9397
2023-03-20 08:56:10 +01:00
sciwhiz12 3cd758647d Fix incorrect variable used for swimming check (#9403)
Because of the incorrect variable, the check to stop sprinting (and stop
swimming) never fired correctly.

1.19.3's `flag5` variable was renamed to `flag7` in 1.19.4; however,
this was not caught during patching because of the fuzzy patcher.

Fixes #9399
2023-03-20 08:44:34 +01:00
sciwhiz12 14bc8d6611 Fix incorrect boolean used for glint effect (#9401)
The `flag1` variable is ultimately controlled by whether the armor slot
being rendered is for the leggings, which explains this bug where the
leggings always had the enchantment glint but not any other armor piece.

Fixes #9394
2023-03-20 08:02:18 +01:00
Redstone_Dubstep d552ce5eac Fixed ModMismatchDisconnectedScreen displaying missing mods wrongly (#9398) 2023-03-19 15:51:03 -07:00
Dennis C f03adc840e Fix misaligned text render type patch (#9391) 2023-03-16 14:44:20 -07:00
LexManos 31e73355c3 Remove thread filter from processing clientside custom payloads. Closes @9390 2023-03-16 11:51:46 -07:00
LexManos 88368dfa1c Fix LivingEntity patch which caused crash while entities got hurt. Closes #9389 2023-03-16 11:50:11 -07:00
matyrobbrt 7e6c8351c3 Fix wrong parameters in Screen#renderTooltipInternal patch (#9387) 2023-03-15 13:05:46 -07:00
LexManos fb20e4fa90 Fix misaligned patch in LevelRenderer. Closes #9385 2023-03-15 13:04:16 -07:00
Jonathan Coates 94c5699a03 Remove our fix for MC-121048 as it has been fixed by Vanilla (#9381) 2023-03-15 11:42:02 -07:00
LexManos 58626d1a22 Fix advancements not loading, bug seems to be fixed by vanilla now. Closes #9384 2023-03-15 11:41:12 -07:00
LexManos 631e72f99d Fixed patch verifier for cases where patches lowered access levels. Closes #9383 2023-03-15 11:39:42 -07:00
LexManos 3fffc18729 Fix crouching while sprinting stopping the player when step height is modified. Closes #9376 2023-03-14 23:56:29 -07:00
337 changed files with 4612 additions and 1512 deletions

No files matched your search

+1
View File
@@ -34,6 +34,7 @@
/repo/
src/generated/resources/.cache/
src/generated_test/resources/.cache/
src/generated_mdk/resources/.cache/
#Patch rejects
/patches-/
+55 -4
View File
@@ -19,6 +19,7 @@ import net.minecraftforge.gradle.common.tasks.SignJar
import net.minecraftforge.gradle.userdev.tasks.RenameJar
import org.apache.tools.ant.filters.ReplaceTokens
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import org.objectweb.asm.Opcodes
plugins {
id 'org.cadixdev.licenser' version '0.6.1'
@@ -53,7 +54,7 @@ ext {
MODLAUNCHER_VERSION = '10.0.8'
SECUREJARHANDLER_VERSION = '2.1.6'
BOOTSTRAPLAUNCHER_VERSION = '1.1.2'
ASM_VERSION = '9.3'
ASM_VERSION = '9.5'
INSTALLER_VERSION = '2.1.+'
MIXIN_VERSION = '0.8.5'
TERMINALCONSOLEAPPENDER_VERSION = '1.2.0'
@@ -1077,11 +1078,38 @@ project(':forge') {
'--mod', 'data_pack_registries_test',
'--mod', 'biome_modifiers_test',
'--mod', 'structure_modifiers_test',
'--mod', 'custom_preset_editor_test',
'--output', rootProject.file('src/generated_test/resources/'),
'--existing', sourceSets.main.resources.srcDirs[0],
'--existing', sourceSets.test.resources.srcDirs[0]
}
}
forge_mdk_data {
parent runs.forge_data
taskName 'forge_mdk_data'
environment 'MOD_CLASSES', 'dummy' // Needed to work around FG limitation, FG will replace this!
ideaModule "${rootProject.name}.${project.name}.test"
mods {
tests { sources sourceSets.test }
}
afterEvaluate {
// Clear forge's main datagen args
args.removeAll {
forgeDataArgs.contains(it instanceof File ? (it as File).absolutePath : it.toString())
}
args '--flat', '--all', '--validate',
'--mod', 'mdk_datagen',
'--output', rootProject.file('src/generated_mdk/resources/'),
'--existing', sourceSets.main.resources.srcDirs[0],
'--existing', sourceSets.test.resources.srcDirs[0]
}
}
}
}
@@ -1174,12 +1202,31 @@ project(':forge') {
}
}
task findFinalizeSpawnTargets(type: BytecodePredicateFinder, dependsOn: ['createJoinedSRG']) {
jar = createJoinedSRG.output
output = rootProject.file('src/main/resources/coremods/finalize_spawn_targets.json')
predicate = {
parent, node, insn ->
'net/minecraft/world/level/BaseSpawner' != parent.name // Ignore this class as we special case it.
&& insn.getOpcode() == Opcodes.INVOKEVIRTUAL
&& insn.name.equals('m_6518_')
&& insn.desc.equals('(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;')
}
}
tasks.register('validateDeprecations', ValidateDeprecations) {
input = tasks.jar.archiveFile
mcVersion = MC_VERSION
}
tasks.jar.finalizedBy 'validateDeprecations'
tasks.register('checkAll') {
dependsOn 'checkLicenses'
group = 'checks'
}
tasks.register('checkAllAndFix') {
dependsOn 'findFieldInstanceChecks', 'checkLicenses'
dependsOn 'findFinalizeSpawnTargets', 'findFieldInstanceChecks', 'checkLicenses'
group = 'checks'
}
@@ -1218,7 +1265,7 @@ project(':forge') {
}
def baseForgeVersionProperty = project.objects.property(String)
baseForgeVersionProperty.set(project.provider { getLatestForgeVersion(MC_VERSION) }.map { MC_VERSION + '-' + it })
baseForgeVersionProperty.set(project.provider { TeamcityRequests.attemptFindBase(rootDir) ?: getLatestForgeVersion(MC_VERSION) })
baseForgeVersionProperty.finalizeValueOnRead()
def jarCompatibilityTaskSetup = { task ->
task.group = 'jar compatibility'
@@ -1584,6 +1631,10 @@ project(':forge') {
rename 'gitignore\\.txt', '.gitignore'
rename 'gitattributes\\.txt', '.gitattributes'
}
from(rootProject.file('src/generated_mdk/resources/')) {
into('src/main/resources/')
exclude '**/.cache/'
}
}
license {
@@ -1735,4 +1786,4 @@ if (System.env.TEAMCITY_VERSION) {
println "##teamcity[setParameter name='env.PUBLISHED_JAVA_FML_ARTIFACT_VERSION' value='${project(':fmlonly').version}']"
}
}
}
}
+4 -3
View File
@@ -4,9 +4,10 @@ repositories {
}
dependencies {
implementation 'org.ow2.asm:asm:9.3'
implementation 'org.ow2.asm:asm-tree:9.3'
implementation 'net.minecraftforge:srgutils:0.4.+'
implementation 'org.ow2.asm:asm:9.5'
implementation 'org.ow2.asm:asm-tree:9.5'
implementation 'net.minecraftforge:srgutils:0.5.+'
implementation 'commons-io:commons-io:2.8.0'
implementation 'com.google.code.gson:gson:2.10'
implementation 'org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r'
}
@@ -6,15 +6,10 @@ import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.objectweb.asm.ClassReader
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.FieldNode
import org.objectweb.asm.tree.MethodNode
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
abstract class BytecodeFinder extends DefaultTask {
@InputFile abstract RegularFileProperty getJar()
@OutputFile abstract RegularFileProperty getOutput()
@@ -33,18 +28,7 @@ abstract class BytecodeFinder extends DefaultTask {
pre()
jar.get().asFile.withInputStream { i ->
new ZipInputStream(i).withCloseable { zin ->
ZipEntry zein
while ((zein = zin.nextEntry) != null) {
if (zein.name.endsWith('.class')) {
def node = new ClassNode(Opcodes.ASM9)
new ClassReader(zin).accept(node, 0)
process(node)
}
}
}
}
Util.processClassNodes(jar.get().asFile, this::process)
post()
outputFile.text = new JsonBuilder(getData()).toPrettyString()
@@ -0,0 +1,32 @@
package net.minecraftforge.forge.tasks
import groovy.transform.CompileStatic
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Internal
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodNode
@CompileStatic
abstract class BytecodePredicateFinder extends BytecodeFinder {
@Internal
abstract Property<Closure<Boolean>> getPredicate()
private final Set<String> matches = new HashSet()
@Override
protected process(ClassNode parent, MethodNode node) {
for (final current : node.instructions) {
if (predicate.get().call(parent, node, current)) {
matches.add(parent.name)
return
}
}
}
@Internal
@Override
protected Object getData() {
return matches.toSorted(Comparator.naturalOrder()) ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
}
}
@@ -6,7 +6,7 @@ import org.gradle.api.provider.SetProperty
abstract class InstallerJar extends Zip {
@Input @Optional abstract SetProperty<String> getPackedDependencies()
InstallerJar() {
archiveClassifier.set('installer')
archiveExtension.set('jar') // Needs to be Zip task to not override Manifest, so set extension
@@ -15,7 +15,7 @@ abstract class InstallerJar extends Zip {
def installerJson = project.tasks.installerJson
def launcherJson = project.tasks.launcherJson
def downloadInstaller = project.tasks.downloadInstaller
dependsOn(installerJson, launcherJson, downloadInstaller)
from(installerJson, launcherJson)
@@ -24,13 +24,13 @@ abstract class InstallerJar extends Zip {
from(project.zipTree(downloadInstaller.output)) {
duplicatesStrategy = 'exclude'
}
if (!System.env.MAVEN_USER) {
if (!System.env.TEAMCITY_VERSION) {
dependsOn(project.universalJar)
from(project.universalJar) {
into '/maven/' + project.group.replace('.', '/') + '/' + project.universalJar.archiveBaseName.get() + '/' + project.version + '/'
}
packedDependencies.get().forEach {
def jarTask = project.rootProject.getTasks().findByPath(it)
dependsOn(jarTask)
@@ -0,0 +1,74 @@
package net.minecraftforge.forge.tasks
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import groovy.transform.CompileStatic
import org.eclipse.jgit.api.Git
import javax.annotation.Nullable
import java.util.stream.Collectors
@CompileStatic
class TeamcityRequests {
public static final Gson GSON = new Gson()
@Nullable
static <T> T jsonRequest(TypeToken<T> clazz, String url) throws Exception {
final HttpURLConnection conn = (HttpURLConnection) URI.create(url).toURL().openConnection()
conn.setRequestProperty('Accept', 'application/json')
conn.setReadTimeout(5 * 1000)
conn.setConnectTimeout(5 * 1000)
conn.connect()
if (conn.responseCode !== 200) {
return null
}
try (final InputStream is = conn.getInputStream()) {
GSON.fromJson(new InputStreamReader(is), clazz.getType())
}
}
@Nullable
static Map<String, Build> buildsByCommit() throws IOException {
final Map<String, Build> builds = [:]
jsonRequest(new TypeToken<Builds>() {}, "https://teamcity.minecraftforge.net/guestAuth/app/rest/builds?fields=build:(revisions,number)&locator=buildType:(id:MinecraftForge_MinecraftForge_MinecraftForge_MinecraftForge__Build),count:300,status:SUCCESS")
?.build?.forEach {
it.revisions.revision.each { rev -> builds[rev.version] = it }
}
return builds
}
@Nullable
static String attemptFindBase(File gitPath) {
try (final git = Git.open(gitPath)) {
final Map<String, Build> buildByCommit = buildsByCommit()
for (final commit in git.log().setMaxCount(100).call()) {
// Find the first commit which was built on CI
final build = buildByCommit[commit.id.name]
if (build) {
return build.number
}
}
} catch (Exception ignored) {}
return null
}
static final class Builds {
public List<Build> build
}
static final class Build {
public String number
public Revisions revisions
}
static final class Revisions {
public int count
public List<Revision> revision
}
static final class Revision {
public String version
}
}
@@ -2,13 +2,20 @@ package net.minecraftforge.forge.tasks
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import org.objectweb.asm.ClassReader
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode
import java.io.File
import java.security.MessageDigest
import java.text.SimpleDateFormat
import java.util.Date
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
public class Util {
static final ASM_LEVEL = Opcodes.ASM9
static void init() {
File.metaClass.sha1 = { ->
MessageDigest md = MessageDigest.getInstance('SHA-1')
@@ -143,8 +150,24 @@ public class Util {
}
}
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"]
static String getLatestForgeVersion(mcVersion) {
final json = new JsonSlurper().parseText(new URL('https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json').getText('UTF-8'))
final ver = json.promos["$mcVersion-latest"]
ver === null ? null : (mcVersion + '-' + ver)
}
static void processClassNodes(File file, Closure process) {
file.withInputStream { i ->
new ZipInputStream(i).withCloseable { zin ->
ZipEntry zein
while ((zein = zin.nextEntry) != null) {
if (zein.name.endsWith('.class')) {
def node = new ClassNode(ASM_LEVEL)
new ClassReader(zin).accept(node, 0)
process(node)
}
}
}
}
}
}
@@ -0,0 +1,92 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.forge.tasks
import net.minecraftforge.srgutils.MinecraftVersion
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.TaskAction
import org.objectweb.asm.tree.AnnotationNode
import org.objectweb.asm.tree.ClassNode
abstract class ValidateDeprecations extends DefaultTask {
@InputFile
abstract RegularFileProperty getInput()
@Input
abstract Property<String> getMcVersion()
ValidateDeprecations() {
this.onlyIf { !System.env.TEAMCITY_VERSION }
}
@TaskAction
protected void exec() {
def mcVer = MinecraftVersion.from(mcVersion.get())
def errors = []
Util.processClassNodes(input.get().asFile) {
processNode(mcVer, errors, it)
}
if (!errors.isEmpty()) {
errors.forEach {
this.logger.error("Deprecated ${it[0]} is marked for removal in ${it[1]} but is not yet removed")
}
throw new IllegalStateException("Found deprecated members marked for removal but not yet removed in ${mcVer}; see log for details")
}
}
protected processNode(MinecraftVersion mcVer, List<String> errors, ClassNode node) {
node.visibleAnnotations?.each { annotation ->
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
"class ${node.name}"
}
}
node.fields?.each { field ->
field.visibleAnnotations?.each { annotation ->
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
"field ${node.name}#${field.name}"
}
}
}
node.methods?.each { method ->
method.visibleAnnotations?.each { annotation ->
ValidateDeprecations.processAnnotations(annotation, mcVer, errors) {
"method ${node.name}#${method.name}${method.desc}"
}
}
}
}
private static void processAnnotations(AnnotationNode annotation, MinecraftVersion mcVer, List<String> errors, Closure context) {
def values = annotation.values
if (values === null)
return
int forRemoval = values.indexOf('forRemoval')
int since = values.indexOf('since')
if (annotation.desc == 'Ljava/lang/Deprecated;' && forRemoval !== -1 && since !== -1 && values.size() >= 4 && values[forRemoval + 1] === true) {
def oldVersion = MinecraftVersion.from(values[since + 1])
def split = ValidateDeprecations.splitDots(oldVersion.toString())
if (split.length < 2)
return
def removeVersion = MinecraftVersion.from("${split[0]}.${split[1] + 1}")
if (removeVersion <= mcVer)
errors.add([context(), removeVersion])
}
}
private static int[] splitDots(String version) {
String[] pts = version.split('\\.')
int[] values = new int[pts.length]
for (int x = 0; x < pts.length; x++)
values[x] = Integer.parseInt(pts[x])
return values
}
}
@@ -1,5 +1,6 @@
package net.minecraftforge.forge.tasks.checks
import net.minecraftforge.forge.tasks.Util
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
@@ -7,7 +8,6 @@ import org.gradle.api.tasks.InputFiles
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
import java.util.zip.ZipEntry
@@ -67,7 +67,7 @@ abstract class CheckExcs extends CheckTask {
private void collectKnown(Collection<String> known) {
binary.get().asFile.withInputStream { i ->
new ZipInputStream(i).withCloseable { zin ->
final visitor = new ClassVisitor(Opcodes.ASM9) {
final visitor = new ClassVisitor(Util.ASM_LEVEL) {
private String cls
@Override
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
@@ -35,6 +35,11 @@ abstract class CheckPatches extends CheckTask {
}
}
}
def accessChange(previous, current) {
//return ACCESS_MAP[previous] < ACCESS_MAP[current]
return previous != current
}
void verifyPatch(Path patch, Reporter reporter, boolean fix, String patchPath, boolean hasS2SArtifact) {
final oldFixedErrors = reporter.fixed.size()
@@ -87,7 +92,7 @@ abstract class CheckPatches extends CheckTask {
pMatcher.group(6) == cMatcher.group(6) && // = ...
pMatcher.group(5) == cMatcher.group(5) && // field name
pMatcher.group(3) == cMatcher.group(3) && // static
(ACCESS_MAP[pMatcher.group(2)] < ACCESS_MAP[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
}
@@ -98,7 +103,7 @@ abstract class CheckPatches extends CheckTask {
pMatcher.group(6) == cMatcher.group(6) && // params
pMatcher.group(5) == cMatcher.group(5) && // <T> void name
pMatcher.group(3) == cMatcher.group(3) && // static
(ACCESS_MAP[pMatcher.group(2)] < ACCESS_MAP[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
}
@@ -109,7 +114,7 @@ abstract class CheckPatches extends CheckTask {
pMatcher.group(6) == cMatcher.group(6) && // ClassName<> extends ...
pMatcher.group(5) == cMatcher.group(5) && // class | interface
pMatcher.group(3) == cMatcher.group(3) && // static
(ACCESS_MAP[pMatcher.group(2)] < ACCESS_MAP[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
(accessChange(pMatcher.group(2), cMatcher.group(2)) || pMatcher.group(4) != cMatcher.group(4))) {
reporter.report("Patch contains access changes or final removal at line ${i + 1}, file: $patchPath", false)
}
}
+3 -1
View File
@@ -7,7 +7,7 @@ Contributing to Forge
3) Follow the code style of the class you're working in (braces on newlines & spaces instead of tabs in Forge classes, inline brackets in patches, etc).
For more information, refer to [the wiki](https://github.com/MinecraftForge/MinecraftForge/wiki/If-you-want-to-contribute-to-Forge)
For more information, refer to [the wiki][Wiki].
Contributor License Agreement
@@ -16,3 +16,5 @@ Contributor License Agreement
- You assign copyright ownership of your contributions to the patches codebase (everything under patches) to Forge, where it will be licensed under the LGPLv2.1 license.
"Forge" is Forge Development LLC, a legally incorporated entity in Oregon, USA.
[Wiki]: https://github.com/MinecraftForge/MinecraftForge/wiki/If-you-want-to-contribute-to-Forge
+26 -16
View File
@@ -2,9 +2,9 @@
MinecraftForge
=============
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.19.3-&query=$.promos["1.19.3-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://files.minecraftforge.net)
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.19.3-&query=$.promos["1.19.3-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)](https://files.minecraftforge.net) [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)](https://discord.gg/UvedJ9m) [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)](https://www.patreon.com/LexManos)
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.19.4-&query=$.promos["1.19.4-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)][Download]
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.19.4-&query=$.promos["1.19.4-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)][Download] [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)][Discord] [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)][Patreon]
Forge is a free, open-source modding API all of your favourite mods use!
@@ -20,7 +20,7 @@ Forge is a free, open-source modding API all of your favourite mods use!
# Installing Forge
Go to [the Forge website](https://files.minecraftforge.net)
Go to [the Forge website][Download]
and select the Minecraft version you wish to get Forge for from the list.
You can download the installer for the *Recommended Build* or the
@@ -29,38 +29,48 @@ You can download the installer for the *Recommended Build* or the
into your vanilla launcher environment, where you can then create a new
profile using that version and play the game!
For support and questions, visit [the Support Forum](https://www.minecraftforge.net/forum/forum/18-support-bug-reports/) or [the Forge Discord server](https://discord.gg/forge).
[Here is a short video from Rorax showing how to install and setup Forge.](https://www.youtube.com/watch?v=lB3ArN_-3Oc)
For support and questions, visit [the Support Forum][Support-Forum] or [the Forge Discord server][Discord].
# Creating Mods
[See the "Getting Started" section in the Forge Documentation](https://mcforge.readthedocs.io/en/latest/gettingstarted/).
[See the "Getting Started" section in the Forge Documentation][Getting-Started].
# Contribute to Forge
If you wish to actually inspect Forge, submit PRs or otherwise work
with Forge itself, you're in the right place!
[See the guide to setting up a Forge workspace](http://mcforge.readthedocs.io/en/latest/forgedev/).
[See the guide to setting up a Forge workspace][ForgeDev].
### Pull requests
[See the "Making Changes and Pull Requests" section in the Forge documentation](https://mcforge.readthedocs.io/en/latest/forgedev/#making-changes-and-pull-requests).
[See the "Making Changes and Pull Requests" section in the Forge documentation][Pull-Requests].
Please read the contributing guidelines found [here](CONTRIBUTING.md) before making a pull request.
Please read the contributing guidelines found [here][Contributing] before making a pull request.
### Contributor License Agreement
We require all contributors to acknowledge the [Forge Contributor License Agreement](https://cla-assistant.io/MinecraftForge/MinecraftForge).
We require all contributors to acknowledge the [Forge Contributor License Agreement][CLA].
Please ensure you have a valid email address associated with your GitHub account to do this. If you have previously
signed it, you should be OK.
#### Donate
*Forge is a large project with many collaborators working on it around the clock. Forge is and will always remain free
to use and modify. However, it costs money to run such a large project as this, so please consider
[becoming a patron](https://www.patreon.com/LexManos).*
[becoming a patron][Patreon].*
[Contributing]: ./CONTRIBUTING.md
[CLA]: https://cla-assistant.io/MinecraftForge/MinecraftForge
[Download]: https://files.minecraftforge.net/
[Forum]: https://www.minecraftforge.net/forum/
[Discord]: https://discord.gg/UvedJ9m
[Documentation]: https://mcforge.readthedocs.io
[Forum]: https://forums.minecraftforge.net/
[Support-Forum]: https://forums.minecraftforge.net/forum/18-support-bug-reports/
[Discord]: https://discord.minecraftforge.net/
[Documentation]: https://docs.minecraftforge.net/
[Getting-Started]: https://docs.minecraftforge.net/en/latest/gettingstarted/
[ForgeDev]: https://docs.minecraftforge.net/en/latest/forgedev/
[Pull-Requests]: https://docs.minecraftforge.net/en/latest/forgedev/#making-changes-and-pull-requests
[Patreon]: https://www.patreon.com/LexManos
+15 -8
View File
@@ -1,7 +1,7 @@
Getting Support Surrounding Forge
=================================
**If you do not want to read the following wall of text, no matter its relevance for helping get your issue resolved quickly, please refer to the [Forge Forums](http://www.minecraftforge.net/forum/forum/18-support-bug-reports/) for support.**
**If you do not want to read the following wall of text, no matter its relevance for helping get your issue resolved quickly, please refer to the [Forge Forums][Bug-Reports] for support.**
Before reporting an issue on this repository's bug tracker, please carefully read this document. There are various resources that are more likely to be able to help you with certain kinds of issues. This document provides instructions on how to determine which place best to report to.
@@ -44,7 +44,7 @@ You can generally tell pretty quickly what caused the error at the head of your
1. If you can find the name of a mod in the trace, that mod most likely is the culprit.
- Be aware that you may find multiple mods as participants of a crash. In that case, you can either report to both or try to reason (using the names in the stacktrace) about which mod is at fault.
2. If you can only find Forge (usually starting with `net.minecraftforge`) alongside Vanilla (usually starting with `net.minecraft`) references, chances are that you have found a bug in Forge. In this case, use one of the various [support channels](#forge-support) listed below.
- The occurence of a single call to Forge somewhere in the stacktrace *does not* warrant a report to Forge if there are mods present in the crash report.
- The occurrence of a single call to Forge somewhere in the stacktrace *does not* warrant a report to Forge if there are mods present in the crash report.
3. If there's no mention of Forge or a mod, but any Vanilla class, you might have found a Vanilla bug. You should probably still report it via the Forge channels first, however, due the nature of modded environments and the rarity of Vanilla crash bugs.
4. Always check whether there's a mention of coremods at the beginning of a crash report. If there is and you can't find any clear culprit, consider reporting to these coremods first, since they are free to change any of the code executed in your environment.
@@ -74,10 +74,10 @@ Please note that this list has to be considered incomplete as there is a large n
If you're certain you've found an issue that is directly caused by Forge, you have the following three platforms available for dealing with it, with decreasing relevance for end-users:
1. **Forge Forums:** There's a dedicated [Support & Bug Report](http://www.minecraftforge.net/forum/forum/18-support-bug-reports/) section on the Forge forums, which is led by team of moderators and volunteers who will try to deal with your reports as quickly as possible. *As a player you should probably report here first.*
- For modders, there also is a separate [Modder Support](http://www.minecraftforge.net/forum/forum/70-modder-support/) section where you can ask all your development-related questions. *You should prefer this section for coding help.*
2. **Forge Discord Server:** You can find a lot of help on the official [Discord Server](https://discord.gg/forge), especially smaller issues that you quickly need help with. *Be aware that the channel is more suited towards development questions, so while you may get support there as a player, you should almost always prefer the forums.*
3. **Forge Issue Tracker:** If you're absolutely certain that you've found an issue in the Forge codebase (e.g. you're a modder yourself and have analyzed the stacktrace and relevant code), don't refrain from reporting it on this repository's [issue tracker](https://github.com/MinecraftForge/MinecraftForge/issues). *Please do not use the issues as a means of getting coding help. For developers, the IRC and the [official documentation](https://mcforge.readthedocs.io) are the best sources of information.*
1. **Forge Forums:** There's a dedicated [Support & Bug Report][Bug-Reports] section on the Forge forums, which is led by team of moderators and volunteers who will try to deal with your reports as quickly as possible. *As a player you should probably report here first.*
- For modders, there also is a separate [Modder Support][Modder-Support] section where you can ask all your development-related questions. *You should prefer this section for coding help.*
2. **Forge Discord Server:** You can find a lot of help on the official [Discord Server][Discord], especially smaller issues that you quickly need help with. *Be aware that the channel is more suited towards development questions, so while you may get support there as a player, you should almost always prefer the forums.*
3. **Forge Issue Tracker:** If you're absolutely certain that you've found an issue in the Forge codebase (e.g. you're a modder yourself and have analyzed the stacktrace and relevant code), don't refrain from reporting it on this repository's [issue tracker](https://github.com/MinecraftForge/MinecraftForge/issues). *Please do not use the issues as a means of getting coding help. For developers, the IRC and the [official documentation][Documentation] are the best sources of information.*
### Mod Support
@@ -99,7 +99,7 @@ Now that you've identified the source of your issue and decided on the correct s
### Preventing Duplicates and Unnecessary Reports
Use the target issue tracker's search functionality to look for issues which have descriptions similar to yours, but make sure to also search for already closed issues. If you can find one, verify it is in fact the same (or a very similar issue) and simply comment on it if you have anything else to contribute to the discussion, such as other steps to reproduce it. *Do not create duplicates of an existing issue, since it only puts extra effort on maintainers to recognize and close/mark them.*
Additionally, always check the *latest* changelogs of Forge and participating mods to find out if the bug was already noticed and fixed by the developer. Often the maintainer may only support newer versions of the game, so also check the changelogs for versions of Minecraft you don't actually actively play. If the issue was adressed already, *do not report it*, even if the fix only exists for a newer version of the game, since the developer probably had a good reason to do so. If your issue only exists with versions of a mod that are for very old versions of the game, also refrain from reporting them, considering most modders only support the two latest versions of Minecraft, if at all.
Additionally, always check the *latest* changelogs of Forge and participating mods to find out if the bug was already noticed and fixed by the developer. Often the maintainer may only support newer versions of the game, so also check the changelogs for versions of Minecraft you don't actually actively play. If the issue was addressed already, *do not report it*, even if the fix only exists for a newer version of the game, since the developer probably had a good reason to do so. If your issue only exists with versions of a mod that are for very old versions of the game, also refrain from reporting them, considering most modders only support the two latest versions of Minecraft, if at all.
### Required Information
If you're certain that your issue went unnoticed up until now, you can get to actually writing up the report. Below you can find a list of the *required* information any bug report should contain:
@@ -144,4 +144,11 @@ After you have written your bug report, it is time to *wait*. Please be *patient
Every project has a different way of dealing with issues, so don't wonder if there's no comment on it, but somebody "labels" it with certain markers. This helps developers to more easily keep track of bugs and priorities. When any further input from you is required, you will be asked specifically. Do not bug anyone through other channels about resolving your issue.
Once your issue is closed, you will know whether it was valid or turned out to be irreproducible. If you included all of the data from above in your report, chances are that the latter won't be the case.
Once your issue is closed, you will know whether it was valid or turned out to be unreproducible. If you included all of the data from above in your report, chances are that the latter won't be the case.
[Bug-Reports]: https://forums.minecraftforge.net/forum/18-support-bug-reports/
[Modder-Support]: https://forums.minecraftforge.net/forum/70-modder-support/
[Discord]: https://discord.minecraftforge.net/
[Documentation]: https://docs.minecraftforge.net/
@@ -5,33 +5,93 @@
package net.minecraftforge.fml;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
public class CrashReportCallables {
public class CrashReportCallables
{
private static final Logger LOGGER = LogUtils.getLogger();
private static final List<ISystemReportExtender> crashCallables = Collections.synchronizedList(new ArrayList<>());
/**
* Register a custom {@link ISystemReportExtender}
*/
public static void registerCrashCallable(ISystemReportExtender callable)
{
crashCallables.add(callable);
}
public static void registerCrashCallable(String headerName, Supplier<String> reportGenerator) {
registerCrashCallable(new ISystemReportExtender() {
/**
* Register a {@link ISystemReportExtender system report extender} with the given header name and content
* generator, which will always be appended to the system report
* @param headerName The name of the system report entry
* @param reportGenerator The report generator to be called when a crash report is built
*/
public static void registerCrashCallable(String headerName, Supplier<String> reportGenerator)
{
registerCrashCallable(new ISystemReportExtender()
{
@Override
public String getLabel() {
public String getLabel()
{
return headerName;
}
@Override
public String get() {
public String get()
{
return reportGenerator.get();
}
});
}
public static List<ISystemReportExtender> allCrashCallables() {
/**
* Register a {@link ISystemReportExtender system report extender} with the given header name and content
* generator, which will only be appended to the system report when the given {@link BooleanSupplier} returns true
* @param headerName The name of the system report entry
* @param reportGenerator The report generator to be called when a crash report is built
* @param active The supplier of the flag to be checked when a crash report is built
*/
public static void registerCrashCallable(String headerName, Supplier<String> reportGenerator, BooleanSupplier active)
{
registerCrashCallable(new ISystemReportExtender()
{
@Override
public String getLabel()
{
return headerName;
}
@Override
public String get()
{
return reportGenerator.get();
}
@Override
public boolean isActive()
{
try
{
return active.getAsBoolean();
}
catch (Throwable t)
{
LOGGER.warn("CrashCallable '{}' threw an exception while checking the active flag, disabling", headerName, t);
return false;
}
}
});
}
public static List<ISystemReportExtender> allCrashCallables()
{
return List.copyOf(crashCallables);
}
}
@@ -11,9 +11,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import com.google.common.base.Stopwatch;
@@ -53,17 +55,29 @@ public class DeferredWorkQueue
public void runTasks() {
if (tasks.isEmpty()) return;
LOGGER.debug(LOADING, "Dispatching synchronous work for work queue {}: {} jobs", modLoadingStage, tasks.size());
RuntimeException aggregate = new RuntimeException();
Stopwatch timer = Stopwatch.createStarted();
tasks.forEach(t->makeRunnable(t, Runnable::run));
tasks.forEach(t -> makeRunnable(t, Runnable::run, aggregate));
timer.stop();
LOGGER.debug(LOADING, "Synchronous work queue completed in {}", timer);
if (aggregate.getSuppressed().length > 0) {
LOGGER.fatal(
LOADING,
"Synchronous work queue completed exceptionally in {}, see suppressed exceptions for details:",
timer,
aggregate
);
//TODO 1.20: throw aggregate exception
} else {
LOGGER.debug(LOADING, "Synchronous work queue completed in {}", timer);
}
}
private static void makeRunnable(TaskInfo ti, Executor executor) {
private static void makeRunnable(TaskInfo ti, Executor executor, RuntimeException aggregate) {
executor.execute(() -> {
Stopwatch timer = Stopwatch.createStarted();
ModLoadingContext.get().setActiveContainer(ti.owner);
try {
ti.future.exceptionally(t -> captureException(ti.owner.getModId(), aggregate, t));
ti.task.run();
} finally {
ModLoadingContext.get().setActiveContainer(null);
@@ -75,13 +89,38 @@ public class DeferredWorkQueue
});
}
private static <T> T captureException(String modId, RuntimeException aggregate, Throwable throwable) {
if (throwable instanceof CompletionException ce) {
throwable = ce.getCause();
}
aggregate.addSuppressed(throwable);
LOGGER.error("Mod '{}' encountered an error in a deferred task:", modId, throwable);
return null;
}
public CompletableFuture<Void> enqueueWork(final ModContainer modInfo, final Runnable work) {
return CompletableFuture.runAsync(work, r->tasks.add(new TaskInfo(modInfo, r)));
return enqueueWork(modInfo, taskInfo -> CompletableFuture.runAsync(work, r -> taskInfo.task = r));
}
public <T> CompletableFuture<T> enqueueWork(final ModContainer modInfo, final Supplier<T> work) {
return CompletableFuture.supplyAsync(work, r->tasks.add(new TaskInfo(modInfo, r)));
return enqueueWork(modInfo, taskInfo -> CompletableFuture.supplyAsync(work, r -> taskInfo.task = r));
}
record TaskInfo(ModContainer owner, Runnable task) {}
private <T> CompletableFuture<T> enqueueWork(final ModContainer modInfo, Function<TaskInfo, CompletableFuture<T>> futureGen) {
TaskInfo taskInfo = new TaskInfo(modInfo);
CompletableFuture<T> future = futureGen.apply(taskInfo);
taskInfo.future = future;
tasks.add(taskInfo);
return future;
}
private static class TaskInfo {
private final ModContainer owner;
private Runnable task;
private CompletableFuture<?> future;
private TaskInfo(ModContainer owner) {
this.owner = owner;
}
}
}
@@ -10,4 +10,9 @@ import java.util.function.Supplier;
public interface ISystemReportExtender extends Supplier<String>
{
String getLabel();
default boolean isActive()
{
return true;
}
}
@@ -82,6 +82,7 @@ public class ModLoader
private boolean loadingStateValid;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private final Optional<Consumer<String>> statusConsumer = StartupMessageManager.modLoaderConsumer();
private final Set<IModLoadingState> completedStates = new HashSet<>();
private ModList modList;
private ModLoader()
@@ -200,6 +201,7 @@ public class ModLoader
statusConsumer.ifPresent(c->c.accept(state.message().apply(this.modList)));
state.inlineRunnable().ifPresent(a->a.accept(this.modList));
state.buildTransition(syncExecutor, parallelExecutor).ifPresent(t->waitForTransition(state, syncExecutor, ticker, t));
completedStates.add(state);
}
private void dispatchAndHandleError(IModLoadingState state, ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor, final Runnable ticker, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
@@ -210,6 +212,7 @@ public class ModLoader
statusConsumer.ifPresent(c->c.accept(state.message().apply(this.modList)));
state.inlineRunnable().ifPresent(a->a.accept(this.modList));
state.buildTransition(syncExecutor, parallelExecutor, preSyncTask, postSyncTask).ifPresent(t->waitForTransition(state, syncExecutor, ticker, t));
completedStates.add(state);
}
private void waitForTransition(final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<Void> transition) {
@@ -296,6 +299,11 @@ public class ModLoader
return get().loadingStateValid;
}
public boolean hasCompletedState(final String stateName) {
IModLoadingState state = stateManager.findState(stateName);
return completedStates.contains(state);
}
public <T extends Event & IModBusEvent> void runEventGenerator(Function<ModContainer, T> generator) {
if (!loadingStateValid) {
LOGGER.error("Cowardly refusing to send event generator to a broken mod state");
@@ -319,6 +327,9 @@ public class ModLoader
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e));
return e;
}
public <T extends Event & IModBusEvent> void postEventWrapContainerInModOrder(T event) {
postEventWithWrapInModOrder(event, (mc, e) -> ModLoadingContext.get().setActiveContainer(mc), (mc, e) -> ModLoadingContext.get().setActiveContainer(null));
}
public <T extends Event & IModBusEvent> void postEventWithWrapInModOrder(T e, BiConsumer<ModContainer, T> pre, BiConsumer<ModContainer, T> post) {
if (!loadingStateValid) {
LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName());
@@ -39,4 +39,13 @@ public class ModStateManager {
nodes.forEach(n->graph.putEdge(lookup.getOrDefault(n.previous(), dummy), n));
return TopologicalSort.topologicalSort(graph, Comparator.comparingInt(nodes::indexOf)).stream().filter(st->st!=dummy).toList();
}
public IModLoadingState findState(final String stateName) {
return stateMap.values()
.stream()
.flatMap(Collection::stream)
.filter(mls -> mls.name().equals(stateName))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown IModLoadingState: " + stateName));
}
}
@@ -10,17 +10,11 @@ import net.minecraftforge.fml.Bindings;
import java.util.function.Function;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
public interface IConfigEvent {
record ConfigConfig(Function<ModConfig, IConfigEvent> loading, Function<ModConfig, IConfigEvent> reloading, @Nullable Function<ModConfig, IConfigEvent> unloading) {
@Deprecated(since = "1.19.3", forRemoval = true)
@ApiStatus.Internal
ConfigConfig(Function<ModConfig, IConfigEvent> loading, Function<ModConfig, IConfigEvent> reloading) {
this(loading, reloading, null);
}
}
record ConfigConfig(Function<ModConfig, IConfigEvent> loading, Function<ModConfig, IConfigEvent> reloading, @Nullable Function<ModConfig, IConfigEvent> unloading) {}
ConfigConfig CONFIGCONFIG = Bindings.getConfigConfiguration().get();
static IConfigEvent reloading(ModConfig modConfig) {
@@ -69,7 +69,7 @@ public class FMLConfig
LOGGER.trace(CORE, "Version check is {}", FMLConfig.runVersionCheck());
LOGGER.trace(CORE, "Default config paths at {}", FMLConfig.defaultConfigPath());
}
FMLPaths.getOrCreateGameRelativePath(Paths.get(FMLConfig.defaultConfigPath()), "default config directory");
FMLPaths.getOrCreateGameRelativePath(Paths.get(FMLConfig.defaultConfigPath()));
}
public static boolean splashScreenEnabled() {
@@ -9,6 +9,8 @@ import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.IEnvironment;
import org.slf4j.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -57,9 +59,13 @@ public enum FMLPaths
for (FMLPaths path : FMLPaths.values())
{
path.absolutePath = rootPath.resolve(path.relativePath).toAbsolutePath().normalize();
if (path.isDirectory)
if (path.isDirectory && !Files.isDirectory(path.absolutePath))
{
FileUtils.getOrCreateDirectory(path.absolutePath, path.name());
try {
Files.createDirectories(path.absolutePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (LOGGER.isDebugEnabled(CORE))
{
@@ -68,8 +74,26 @@ public enum FMLPaths
}
}
/**
* @deprecated Use {@link #getOrCreateGameRelativePath(Path)} instead.
*/
@Deprecated(forRemoval = true, since = "1.19.4")
public static Path getOrCreateGameRelativePath(Path path, String name) {
return FileUtils.getOrCreateDirectory(FMLPaths.GAMEDIR.get().resolve(path), name);
return getOrCreateGameRelativePath(path);
}
public static Path getOrCreateGameRelativePath(Path path) {
Path gameFolderPath = FMLPaths.GAMEDIR.get().resolve(path);
if (!Files.isDirectory(gameFolderPath)) {
try {
Files.createDirectories(gameFolderPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return gameFolderPath;
}
public Path relative() {
@@ -10,37 +10,27 @@ import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class FileUtils
{
private static final Logger LOGGER = LogUtils.getLogger();
/**
* @deprecated Use normal Java NIO methods instead
*/
@Deprecated(forRemoval = true, since = "1.19.4")
public static Path getOrCreateDirectory(Path dirPath, String dirLabel) {
if (!Files.isDirectory(dirPath.getParent())) {
getOrCreateDirectory(dirPath.getParent(), "parent of "+dirLabel);
}
if (!Files.isDirectory(dirPath))
{
LOGGER.debug(CORE, "Making {} directory : {}", dirLabel, dirPath);
try {
Files.createDirectory(dirPath);
Files.createDirectories(dirPath);
} catch (IOException e) {
if (e instanceof FileAlreadyExistsException) {
LOGGER.error(CORE, "Failed to create {} directory - there is a file in the way", dirLabel);
} else {
LOGGER.error(CORE, "Problem with creating {} directory (Permissions?)", dirLabel, e);
}
throw new RuntimeException("Problem creating directory", e);
}
LOGGER.debug(CORE, "Created {} directory : {}", dirLabel, dirPath);
} else {
LOGGER.debug(CORE, "Found existing {} directory : {}", dirLabel, dirPath);
}
return dirPath;
}
@@ -54,7 +44,7 @@ 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()));
@@ -52,7 +52,7 @@ public class ClientModLoader
}
}
}
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager, ClientPackSource metadataSerializer)
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager)
{
// force log4j to shutdown logging in a shutdown hook. This is because we disable default shutdown hook so the server properly logs it's shutdown
Runtime.getRuntime().addShutdownHook(new Thread(LogManager::shutdown));
@@ -0,0 +1,56 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fmlonlyserver;
import joptsimple.OptionParser;
import net.minecraftforge.fml.LoadingFailedException;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingWarning;
import net.minecraftforge.fml.ModWorkManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.util.List;
import static net.minecraftforge.fml.Logging.LOADING;
public class ServerModLoader
{
private static final Logger LOGGER = LogManager.getLogger();
private static boolean hasErrors = false;
public static void addOptions(OptionParser parser)
{
// We consume this argument as we use it in the launcher and the client side.
parser.accepts("gameDir").withRequiredArg().ofType(File.class).defaultsTo(new File("."));
}
public static void load()
{
try
{
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().loadMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
ModLoader.get().finishMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), () -> {});
} catch (LoadingFailedException error)
{
ServerModLoader.hasErrors = true;
throw error;
}
List<ModLoadingWarning> warnings = ModLoader.get().getWarnings();
if (!warnings.isEmpty())
{
LOGGER.warn(LOADING, "Mods loaded with {} warnings", warnings.size());
warnings.forEach(warning -> LOGGER.warn(LOADING, warning.formatToString()));
}
}
public static boolean hasErrors()
{
return ServerModLoader.hasErrors;
}
}
@@ -1,3 +1,4 @@
{
"load_fml_client": "coremods/load_fml_client.js"
"load_fml_client": "coremods/load_fml_client.js",
"load_fml_server": "coremods/load_fml_server.js"
}
@@ -15,16 +15,13 @@ function initializeCoreMod() {
var meth = ASMAPI.getMethodNode();
var resourcePackRepository = ASMAPI.mapField("f_91038_")
var resourceManager = ASMAPI.mapField("f_91036_")
var clientPackSource = ASMAPI.mapField("f_91037_")
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/client/Minecraft", resourcePackRepository, "Lnet/minecraft/server/packs/repository/PackRepository;");
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/client/Minecraft", resourceManager, "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;");
meth.visitVarInsn(Opcodes.ALOAD, 0);
meth.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/client/Minecraft", clientPackSource, "Lnet/minecraft/client/resources/ClientPackSource;");
meth.visitMethodInsn(Opcodes.INVOKESTATIC, "net/minecraftforge/fmlonlyclient/ClientModLoader", "begin", "(Lnet/minecraft/client/Minecraft;Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/server/packs/resources/ReloadableResourceManager;Lnet/minecraft/client/resources/ClientPackSource;)V", false)
meth.visitMethodInsn(Opcodes.INVOKESTATIC, "net/minecraftforge/fmlonlyclient/ClientModLoader", "begin", "(Lnet/minecraft/client/Minecraft;Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/server/packs/resources/ReloadableResourceManager;)V", false)
for (var i=0; i<methodNode.instructions.size(); i++) {
var ain = methodNode.instructions.get(i);
if (ain.getOpcode() == Opcodes.PUTFIELD && ain.name.equals(resourceManager)) {
@@ -0,0 +1,35 @@
var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI')
var Opcodes = Java.type('org.objectweb.asm.Opcodes')
function initializeCoreMod() {
return {
'minecraft': {
'target': {
'type': 'METHOD',
'class': 'net.minecraft.server.Main',
'methodName': 'main',
'methodDesc': '([Ljava/lang/String;)V'
},
'transformer': function(methodNode) {
var meth = ASMAPI.getMethodNode();
meth.visitMethodInsn(Opcodes.INVOKESTATIC, 'net/minecraftforge/fmlonlyserver/ServerModLoader', 'load', '()V', false)
var methOptions = ASMAPI.getMethodNode();
methOptions.visitIntInsn(Opcodes.ALOAD, 1);
methOptions.visitMethodInsn(Opcodes.INVOKESTATIC, 'net/minecraftforge/fmlonlyserver/ServerModLoader', 'addOptions', '(Ljoptsimple/OptionParser;)V', false)
for (var i=0; i<methodNode.instructions.size(); i++) {
var ain = methodNode.instructions.get(i);
if (ain.getOpcode() == Opcodes.INVOKESPECIAL && ain.owner == 'joptsimple/OptionParser' && ain.name == '<init>' && ain.desc == '()V') {
// Inject after the STORE
methodNode.instructions.insert(methodNode.instructions.get(i + 1), methOptions.instructions);
} else if (ain.getOpcode() == Opcodes.INVOKESTATIC && ain.owner == 'net/minecraft/Util' && ain.name == ASMAPI.mapMethod('m_137584_') /* startTimerHackThread */ && ain.desc == '()V') {
methodNode.instructions.insert(ain, meth.instructions);
break; // By this point we've already reached the first injection point so break
}
}
return methodNode;
}
},
}
}
-8
View File
@@ -1,8 +0,0 @@
{
"pack": {
"description": "examplemod resources",
"pack_format": 12,
"forge:resource_pack_format": 12,
"forge:data_pack_format": 10
}
}
@@ -1,10 +0,0 @@
--- a/net/minecraft/advancements/AdvancementList.java
+++ b/net/minecraft/advancements/AdvancementList.java
@@ -90,6 +_,7 @@
}
}
+ net.minecraftforge.common.AdvancementLoadFix.buildSortedTrees(this.f_139327_);
f_139325_.info("Loaded {} advancements", (int)this.f_139326_.size());
}
@@ -60,29 +60,15 @@
this.f_91064_ = new DebugRenderer(this);
this.f_238717_ = new RealmsDataFetcher(RealmsClient.m_239151_(this));
RenderSystem.m_69900_(this::m_91113_);
@@ -545,6 +_,21 @@
@@ -545,6 +_,7 @@
TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false);
}
+ net.minecraftforge.gametest.ForgeGameTestHooks.registerGametests();
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.RegisterClientReloadListenersEvent(this.f_91036_));
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.RegisterLayerDefinitions());
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.RegisterRenderers());
+ net.minecraftforge.client.textures.TextureAtlasSpriteLoaderManager.init();
+ net.minecraftforge.client.gui.ClientTooltipComponentManager.init();
+ net.minecraftforge.client.EntitySpectatorShaderManager.init();
+ net.minecraftforge.client.ForgeHooksClient.onRegisterKeyMappings(f_91066_);
+ net.minecraftforge.client.RecipeBookManager.init();
+ net.minecraftforge.client.gui.overlay.GuiOverlayManager.init();
+ net.minecraftforge.client.DimensionSpecialEffectsManager.init();
+ net.minecraftforge.client.NamedRenderTypeManager.init();
+ net.minecraftforge.client.ColorResolverManager.init();
+ net.minecraftforge.client.ItemDecoratorHandler.init();
+
+ net.minecraftforge.client.ForgeHooksClient.initClientHooks(this, this.f_91036_);
this.f_90990_.m_85409_(this.f_91066_.m_231817_().m_231551_());
this.f_90990_.m_85424_(this.f_91066_.m_232123_().m_231551_());
this.f_90990_.m_85426_();
@@ -568,26 +_,24 @@
@@ -568,26 +_,26 @@
}
this.f_167847_.m_168556_();
@@ -99,6 +85,8 @@
+
+ this.m_91152_(new TitleScreen(true));
+ }, this.m_239210_()));
+ } else if (this.f_91066_.f_263744_) {
+ this.m_91152_(new AccessibilityOnboardingScreen(this.f_91066_));
+ } else {
+ this.m_91152_(new TitleScreen(true));
+ }
@@ -285,21 +273,16 @@
this.f_91074_.m_6674_(InteractionHand.MAIN_HAND);
}
}
@@ -1581,14 +_,20 @@
@@ -1581,6 +_,8 @@
return false;
} else {
boolean flag = false;
- switch (this.f_91077_.m_6662_()) {
+ var inputEvent = net.minecraftforge.client.ForgeHooksClient.onClickInput(0, this.f_91066_.f_92096_, InteractionHand.MAIN_HAND);
+ HitResult.Type hitType = this.f_91077_.m_6662_();
+ if (this.f_91077_ instanceof EntityHitResult entityHit) { // Forge: Perform attack range checks here, instead of in GameRenderer#pick, so extended-reach interactions work.
+ if (!f_91074_.canHit(entityHit.m_82443_(), 0)) hitType = HitResult.Type.MISS; // No padding in client code.
+ }
+ if (!inputEvent.isCanceled())
+ switch(hitType) {
switch (this.f_91077_.m_6662_()) {
case ENTITY:
this.f_91072_.m_105223_(this.f_91074_, ((EntityHitResult)this.f_91077_).m_82443_());
break;
@@ -1588,7 +_,7 @@
case BLOCK:
BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_;
BlockPos blockpos = blockhitresult.m_82425_();
@@ -331,14 +314,7 @@
ItemStack itemstack = this.f_91074_.m_21120_(interactionhand);
if (!itemstack.m_246617_(this.f_91073_.m_246046_())) {
return;
@@ -1632,13 +_,14 @@
return;
}
+ 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);
@@ -1638,7 +_,7 @@
}
if (interactionresult.m_19077_()) {
@@ -1,13 +1,5 @@
--- a/net/minecraft/client/gui/Gui.java
+++ b/net/minecraft/client/gui/Gui.java
@@ -374,6 +_,7 @@
if (this.f_92986_.f_91076_ != null && this.f_92986_.f_91076_ instanceof LivingEntity && f >= 1.0F) {
flag = this.f_92986_.f_91074_.m_36333_() > 5.0F;
flag &= this.f_92986_.f_91076_.m_6084_();
+ flag &= this.f_92986_.f_91074_.canHit(this.f_92986_.f_91076_, 0);
}
int j = this.f_92978_ / 2 - 7 + 16;
@@ -428,6 +_,10 @@
for(MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
@@ -58,15 +50,6 @@
}
}
@@ -924,7 +_,7 @@
RenderSystem.m_157429_(1.0F, 1.0F, 1.0F, 1.0F);
}
- public void m_264541_(PoseStack p_265563_, float p_265127_) {
+ protected void m_264541_(PoseStack p_265563_, float p_265127_) {
RenderSystem.m_69465_();
RenderSystem.m_69458_(false);
float f = (float)Math.min(this.f_92977_, this.f_92978_);
@@ -1054,7 +_,7 @@
ItemStack itemstack = this.f_92986_.f_91074_.m_150109_().m_36056_();
if (itemstack.m_41619_()) {
@@ -0,0 +1,11 @@
--- a/net/minecraft/client/gui/screens/ChatScreen.java
+++ b/net/minecraft/client/gui/screens/ChatScreen.java
@@ -225,7 +_,7 @@
this.f_96541_.f_91074_.f_108617_.m_246175_(p_242400_);
}
- return true;
+ return f_96541_.f_91080_ == this; // FORGE: Prevent closing the screen if another screen has been opened.
}
}
@@ -103,15 +103,19 @@
int l = vector2ic.x();
int i1 = vector2ic.y();
p_263064_.m_85836_();
@@ -307,6 +_,8 @@
@@ -307,9 +_,10 @@
RenderSystem.m_157427_(GameRenderer::m_172811_);
bufferbuilder.m_166779_(VertexFormat.Mode.QUADS, DefaultVertexFormat.f_85815_);
Matrix4f matrix4f = p_263064_.m_85850_().m_252922_();
+ // TODO 1.19.3: Tooltip rendering changed, rethink the color event.
+ // net.minecraftforge.client.event.RenderTooltipEvent.Color colorEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipColor(this.tooltipStack, p_263064_, k1, l1, preEvent.getFont(), p_262990_);
TooltipRenderUtil.m_262796_((p_262872_, p_262873_, p_262874_, p_262875_, p_262876_, p_262877_, p_262878_, p_262879_, p_262880_) -> {
- TooltipRenderUtil.m_262796_((p_262872_, p_262873_, p_262874_, p_262875_, p_262876_, p_262877_, p_262878_, p_262879_, p_262880_) -> {
+ net.minecraftforge.client.event.RenderTooltipEvent.Color colorEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipColor(this.tooltipStack, p_263064_, l, i1, preEvent.getFont(), p_262990_);
+ TooltipRenderUtil.renderTooltipBackground((p_262872_, p_262873_, p_262874_, p_262875_, p_262876_, p_262877_, p_262878_, p_262879_, p_262880_) -> {
GuiComponent.m_93123_(p_262872_, p_262873_, p_262874_, p_262875_, p_262876_, p_262877_, p_262878_, p_262879_, p_262880_);
}, matrix4f, bufferbuilder, l, i1, i, j, 400);
- }, matrix4f, bufferbuilder, l, i1, i, j, 400);
+ }, matrix4f, bufferbuilder, l, i1, i, j, 400, colorEvent.getBackgroundStart(), colorEvent.getBackgroundEnd(), colorEvent.getBorderStart(), colorEvent.getBorderEnd());
RenderSystem.m_69482_();
RenderSystem.m_69478_();
RenderSystem.m_69453_();
@@ -320,7 +_,7 @@
for(int l1 = 0; l1 < p_262990_.size(); ++l1) {
@@ -126,29 +130,32 @@
for(int i2 = 0; i2 < p_262990_.size(); ++i2) {
ClientTooltipComponent clienttooltipcomponent2 = p_262990_.get(i2);
- clienttooltipcomponent2.m_183452_(this.f_96547_, l, k1, p_263064_, this.f_96542_);
+ clienttooltipcomponent2.m_183452_(preEvent.getFont(), k1, i1, p_263064_, this.f_96542_);
+ clienttooltipcomponent2.m_183452_(preEvent.getFont(), l, k1, p_263064_, this.f_96542_);
k1 += clienttooltipcomponent2.m_142103_() + (i2 == 0 ? 2 : 0);
}
@@ -438,8 +_,18 @@
@@ -432,7 +_,10 @@
this.f_96543_ = p_96608_;
this.f_96544_ = p_96609_;
if (!this.f_267454_) {
+ if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Pre(this, this.f_96540_, this::addEventWidget, this::m_169411_))) {
this.m_7856_();
+ }
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Post(this, this.f_96540_, this::addEventWidget, this::m_169411_));
} else {
this.m_267719_();
}
this.f_267454_ = true;
+ java.util.function.Consumer<GuiEventListener> add = (b) -> {
+ if (b instanceof Renderable r)
+ this.f_169369_.add(r);
+ if (b instanceof NarratableEntry ne)
+ this.f_169368_.add(ne);
+ f_96540_.add(b);
+ };
+ if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Pre(this, this.f_96540_, add, this::m_169411_))) {
this.m_169407_(false);
this.m_169378_(f_169370_);
@@ -445,7 +_,10 @@
protected void m_232761_() {
this.m_169413_();
this.m_264131_();
+ if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Pre(this, this.f_96540_, this::addEventWidget, this::m_169411_))) {
this.m_7856_();
+ }
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Post(this, this.f_96540_, add, this::m_169411_));
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.ScreenEvent.Init.Post(this, this.f_96540_, this::addEventWidget, this::m_169411_));
}
protected void m_232761_() {
public List<? extends GuiEventListener> m_6702_() {
@@ -467,6 +_,7 @@
public void m_7333_(PoseStack p_96557_) {
if (this.f_96541_.f_91073_ != null) {
@@ -165,14 +172,28 @@
}
public boolean m_7043_() {
@@ -570,6 +_,10 @@
@@ -572,6 +_,10 @@
public void m_7400_(List<Path> p_96591_) {
}
public void m_7400_(List<Path> p_96591_) {
+ }
+
+ public Minecraft getMinecraft() {
+ return this.f_96541_;
}
+ }
+
private void m_169380_(long p_169381_, boolean p_169382_) {
this.f_169377_ = Util.m_137550_() + p_169381_;
if (p_169382_) {
@@ -733,5 +_,13 @@
this.f_169421_ = p_169425_;
this.f_169422_ = p_169426_;
}
+ }
+
+ private void addEventWidget(GuiEventListener b) {
+ if (b instanceof Renderable r)
+ this.f_169369_.add(r);
+ if (b instanceof NarratableEntry ne)
+ this.f_169368_.add(ne);
+ f_96540_.add(b);
}
}
@@ -0,0 +1,49 @@
--- a/net/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil.java
+++ b/net/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil.java
@@ -18,16 +_,21 @@
private static final int f_262743_ = 1344798847;
public static void m_262796_(TooltipRenderUtil.BlitPainter p_262929_, Matrix4f p_263052_, BufferBuilder p_263082_, int p_263046_, int p_263101_, int p_263024_, int p_262926_, int p_263038_) {
+ renderTooltipBackground(p_262929_, p_263052_, p_263082_, p_263046_, p_263101_, p_263024_, p_262926_, p_263038_, f_262744_, f_262744_, f_262725_, f_262743_);
+ }
+
+ // Forge: Allow specifying colors for the inner border gradient and a gradient instead of a single color for the background and outer border
+ public static void renderTooltipBackground(TooltipRenderUtil.BlitPainter p_262929_, Matrix4f p_263052_, BufferBuilder p_263082_, int p_263046_, int p_263101_, int p_263024_, int p_262926_, int p_263038_, int backgroundTop, int backgroundBottom, int borderTop, int borderBottom) {
int i = p_263046_ - 3;
int j = p_263101_ - 3;
int k = p_263024_ + 3 + 3;
int l = p_262926_ + 3 + 3;
- m_262855_(p_262929_, p_263052_, p_263082_, i, j - 1, k, p_263038_, -267386864);
- m_262855_(p_262929_, p_263052_, p_263082_, i, j + l, k, p_263038_, -267386864);
- m_262805_(p_262929_, p_263052_, p_263082_, i, j, k, l, p_263038_, -267386864);
- m_262798_(p_262929_, p_263052_, p_263082_, i - 1, j, l, p_263038_, -267386864);
- m_262798_(p_262929_, p_263052_, p_263082_, i + k, j, l, p_263038_, -267386864);
- m_262846_(p_262929_, p_263052_, p_263082_, i, j + 1, k, l, p_263038_, 1347420415, 1344798847);
+ m_262855_(p_262929_, p_263052_, p_263082_, i, j - 1, k, p_263038_, backgroundTop);
+ m_262855_(p_262929_, p_263052_, p_263082_, i, j + l, k, p_263038_, backgroundBottom);
+ renderRectangle(p_262929_, p_263052_, p_263082_, i, j, k, l, p_263038_, backgroundTop, backgroundBottom);
+ m_262849_(p_262929_, p_263052_, p_263082_, i - 1, j, l, p_263038_, backgroundTop, backgroundBottom);
+ m_262849_(p_262929_, p_263052_, p_263082_, i + k, j, l, p_263038_, backgroundTop, backgroundBottom);
+ m_262846_(p_262929_, p_263052_, p_263082_, i, j + 1, k, l, p_263038_, borderTop, borderBottom);
}
private static void m_262846_(TooltipRenderUtil.BlitPainter p_262974_, Matrix4f p_263030_, BufferBuilder p_263061_, int p_262982_, int p_262912_, int p_262946_, int p_263049_, int p_263118_, int p_263104_, int p_262979_) {
@@ -49,8 +_,17 @@
p_262966_.m_262815_(p_263094_, p_262943_, p_262949_, p_263068_, p_262949_ + p_263111_, p_263068_ + 1, p_263095_, p_262918_, p_262918_);
}
+ /**
+ * @deprecated Forge: Use gradient overload instead
+ */
+ @Deprecated
private static void m_262805_(TooltipRenderUtil.BlitPainter p_262933_, Matrix4f p_263035_, BufferBuilder p_263084_, int p_262945_, int p_262955_, int p_263017_, int p_262978_, int p_262950_, int p_262931_) {
- p_262933_.m_262815_(p_263035_, p_263084_, p_262945_, p_262955_, p_262945_ + p_263017_, p_262955_ + p_262978_, p_262950_, p_262931_, p_262931_);
+ renderRectangle(p_262933_, p_263035_, p_263084_, p_262945_, p_262955_, p_263017_, p_262978_, p_262950_, p_262931_, p_262931_);
+ }
+
+ // Forge: Allow specifying a gradient instead of a single color for the background
+ private static void renderRectangle(TooltipRenderUtil.BlitPainter p_262933_, Matrix4f p_263035_, BufferBuilder p_263084_, int p_262945_, int p_262955_, int p_263017_, int p_262978_, int p_262950_, int p_262931_, int colorTo) {
+ p_262933_.m_262815_(p_263035_, p_263084_, p_262945_, p_262955_, p_262945_ + p_263017_, p_262955_ + p_262978_, p_262950_, p_262931_, colorTo);
}
@FunctionalInterface
@@ -1,27 +1,13 @@
--- a/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
+++ b/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
@@ -119,7 +_,8 @@
@@ -119,6 +_,7 @@
public static void m_232896_(Minecraft p_232897_, @Nullable Screen p_232898_) {
m_232899_(p_232897_, f_232866_);
PackRepository packrepository = new PackRepository(new ServerPacksSource());
- WorldLoader.InitConfig worldloader$initconfig = m_245574_(packrepository, WorldDataConfiguration.f_244649_);
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.event.AddPackFindersEvent(net.minecraft.server.packs.PackType.SERVER_DATA, packrepository::addPackFinder));
+ WorldLoader.InitConfig worldloader$initconfig = m_245574_(packrepository, new WorldDataConfiguration(new DataPackConfig(ImmutableList.of("vanilla"), ImmutableList.of()), FeatureFlags.f_244332_)); // FORGE: Load vanilla fallback with vanilla datapacks.
WorldLoader.InitConfig worldloader$initconfig = m_245574_(packrepository, WorldDataConfiguration.f_244649_);
CompletableFuture<WorldCreationContext> completablefuture = WorldLoader.m_214362_(worldloader$initconfig, (p_247792_) -> {
return new WorldLoader.DataLoadOutput<>(new CreateWorldScreen.DataPackReloadCookie(new WorldGenSettings(WorldOptions.m_247394_(), WorldPresets.m_246552_(p_247792_.f_244104_())), p_247792_.f_244127_()), p_247792_.f_243759_());
}, (p_247798_, p_247799_, p_247800_, p_247801_) -> {
@@ -127,7 +_,10 @@
return new WorldCreationContext(p_247801_.f_243966_(), p_247800_, p_247799_, p_247801_.f_243979_());
}, Util.m_183991_(), p_232897_);
p_232897_.m_18701_(completablefuture::isDone);
- p_232897_.m_91152_(new CreateWorldScreen(p_232897_, p_232898_, completablefuture.join(), Optional.of(WorldPresets.f_226437_), OptionalLong.empty()));
+ // FORGE: Force load mods' datapacks after setting screen and ensure datapack selection reverts to vanilla if invalid.
+ CreateWorldScreen createWorldScreen = new CreateWorldScreen(p_232897_, p_232898_, completablefuture.join().withDataConfiguration(new WorldDataConfiguration(new DataPackConfig(ImmutableList.of("vanilla"), ImmutableList.of()), FeatureFlags.f_244332_)), Optional.of(WorldPresets.f_226437_), OptionalLong.empty());
+ p_232897_.m_91152_(createWorldScreen);
+ createWorldScreen.m_269443_(packrepository, true, createWorldScreen::m_267734_);
}
public static CreateWorldScreen m_275847_(Minecraft p_276017_, @Nullable Screen p_276029_, LevelSettings p_276055_, WorldCreationContext p_276028_, @Nullable Path p_276040_) {
@@ -368,7 +_,7 @@
if (p_269627_) {
p_270552_.accept(this.f_267389_.m_267573_().f_243842_());
@@ -0,0 +1,13 @@
--- a/net/minecraft/client/gui/screens/worldselection/PresetEditor.java
+++ b/net/minecraft/client/gui/screens/worldselection/PresetEditor.java
@@ -28,6 +_,10 @@
@OnlyIn(Dist.CLIENT)
public interface PresetEditor {
+ /**
+ * @deprecated Forge: Use {@link net.minecraftforge.client.PresetEditorManager#get(ResourceKey)} instead.
+ */
+ @Deprecated
Map<Optional<ResourceKey<WorldPreset>>, PresetEditor> f_232950_ = Map.of(Optional.of(WorldPresets.f_226438_), (p_232974_, p_232975_) -> {
ChunkGenerator chunkgenerator = p_232975_.f_243796_().m_246737_();
RegistryAccess registryaccess = p_232975_.m_246480_();
@@ -0,0 +1,11 @@
--- a/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
+++ b/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
@@ -226,7 +_,7 @@
@Nullable
public PresetEditor m_267744_() {
Holder<WorldPreset> holder = this.m_267828_().f_267398_();
- return holder != null ? PresetEditor.f_232950_.get(holder.m_203543_()) : null;
+ return holder != null ? holder.m_203543_().map(net.minecraftforge.client.PresetEditorManager::get).orElse(null) : null; // FORGE: redirect lookup to expanded map
}
public List<WorldCreationUiState.WorldTypeEntry> m_267815_() {
@@ -12,7 +12,7 @@
}
this.f_104411_.m_171649_(chunkpos);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.ChunkEvent.Load(levelchunk));
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.ChunkEvent.Load(levelchunk, false));
return levelchunk;
}
}
@@ -72,7 +72,7 @@
}
public void m_7413_(ClientboundCustomPayloadPacket p_105004_) {
+ if (!f_104888_.m_18695_() && net.minecraftforge.network.NetworkHooks.onCustomPayload(p_105004_, this.f_104885_)) return;
+ if (net.minecraftforge.network.NetworkHooks.onCustomPayload(p_105004_, this.f_104885_)) return;
PacketUtils.m_131363_(p_105004_, this, this.f_104888_);
ResourceLocation resourcelocation = p_105004_.m_132042_();
FriendlyByteBuf friendlybytebuf = null;
@@ -84,7 +84,7 @@
public float m_105286_() {
- return this.f_105197_.m_46408_() ? 5.0F : 4.5F;
+ return (float) this.f_105189_.f_91074_.getReachDistance();
+ return (float) this.f_105189_.f_91074_.getBlockReach();
}
public void m_105287_() {
@@ -64,7 +64,7 @@
+ boolean flag8 = flag7 || this.f_19862_ && !this.f_185931_ || this.m_20069_() && !this.m_5842_() || (this.isInFluidType((fluidType, height) -> this.canSwimInFluidType(fluidType)) && !this.canStartSwimming());
if (this.m_6069_()) {
- if (!this.f_19861_ && !this.f_108618_.f_108573_ && flag7 || !this.m_20069_()) {
+ if (!this.f_19861_ && !this.f_108618_.f_108573_ && flag5 || !(this.m_20069_() || this.isInFluidType((fluidType, height) -> this.canSwimInFluidType(fluidType)))) {
+ if (!this.f_19861_ && !this.f_108618_.f_108573_ && flag7 || !(this.m_20069_() || this.isInFluidType((fluidType, height) -> this.canSwimInFluidType(fluidType)))) {
this.m_6858_(false);
}
} else if (flag8) {
@@ -17,37 +17,49 @@
} catch (IOException ioexception) {
list1.forEach((p_172729_) -> {
p_172729_.getFirst().close();
@@ -678,19 +_,21 @@
@@ -673,12 +_,13 @@
this.f_109059_.m_91307_().m_6180_("pick");
this.f_109059_.f_91076_ = null;
double d0 = (double)this.f_109059_.f_91072_.m_105286_();
- this.f_109059_.f_91077_ = entity.m_19907_(d0, p_109088_, false);
+ double entityReach = this.f_109059_.f_91074_.getEntityReach(); // Note - MC-76493 - We must validate players cannot click-through objects.
+ this.f_109059_.f_91077_ = entity.m_19907_(Math.max(d0, entityReach), p_109088_, false); // Run pick() with the max of the two, so we can prevent click-through.
Vec3 vec3 = entity.m_20299_(p_109088_);
boolean flag = false;
int i = 3;
double d1 = d0;
+ double atkRange = this.f_109059_.f_91074_.getAttackRange();
if (this.f_109059_.f_91072_.m_105291_()) {
- d1 = 6.0D;
+ d1 = Math.max(d0, atkRange);
- if (this.f_109059_.f_91072_.m_105291_()) {
+ if (false && this.f_109059_.f_91072_.m_105291_()) {
d1 = 6.0D;
d0 = d1;
} else {
- if (d0 > 3.0D) {
+ if (d0 > atkRange) {
flag = true;
}
@@ -688,10 +_,19 @@
d0 = d0;
+ d0 = d1 = Math.max(d0, atkRange); // Pick entities with the max of the reach distance and attack range.
}
+ d0 = d1 = Math.max(d0, entityReach); // Pick entities with the max of both for the same reason.
d1 *= d1;
- if (this.f_109059_.f_91077_ != null) {
+ if (this.f_109059_.f_91077_ != null && this.f_109059_.f_91077_.m_6662_() != HitResult.Type.MISS) { // Add != MISS to ensure Attack Range is not clamped at the value of Reach Distance.
+ // If we picked a block, we need to ignore entities past that block. Added != MISS check to not truncate on failed picks.
+ // Also fixes MC-250858
+ if (this.f_109059_.f_91077_ != null && this.f_109059_.f_91077_.m_6662_() != HitResult.Type.MISS) {
d1 = this.f_109059_.f_91077_.m_82450_().m_82557_(vec3);
+ double blockReach = this.f_109059_.f_91074_.getBlockReach();
+ // Discard the result as a miss if it is outside the block reach.
+ if (d1 > blockReach * blockReach) {
+ Vec3 pos = this.f_109059_.f_91077_.m_82450_();
+ this.f_109059_.f_91077_ = BlockHitResult.m_82426_(pos, Direction.m_122366_(vec3.f_82479_, vec3.f_82480_, vec3.f_82481_), BlockPos.m_274446_(pos));
+ }
}
Vec3 vec31 = entity.m_20252_(1.0F);
@@ -705,7 +_,7 @@
Entity entity1 = entityhitresult.m_82443_();
Vec3 vec33 = entityhitresult.m_82450_();
double d2 = vec3.m_82557_(vec33);
- if (flag && d2 > 9.0D) {
+ if (false && flag && d2 > 9.0D) { //Forge: Always keep the entity result to allow for extended reach interactions.
+ if (d2 > d1 || d2 > entityReach * entityReach) { // Discard if the result is behind a block, or past the entity reach max. The var "flag" no longer has a use.
this.f_109059_.f_91077_ = BlockHitResult.m_82426_(vec33, Direction.m_122366_(vec31.f_82479_, vec31.f_82480_, vec31.f_82481_), BlockPos.m_274446_(vec33));
} else if (d2 < d1 || this.f_109059_.f_91077_ == null) {
this.f_109059_.f_91077_ = entityhitresult;
@@ -225,24 +225,24 @@
if (recorditem != null) {
this.f_109461_.f_91065_.m_93055_(recorditem.m_43050_());
}
@@ -2503,7 +_,7 @@
case 1010:
Item item = Item.m_41445_(p_234307_);
if (item instanceof RecordItem recorditem) {
- this.m_109514_(recorditem.m_43051_(), p_234306_);
+ this.playStreamingMusic(recorditem.m_43051_(), p_234306_, recorditem);
}
break;
case 1011:
@@ -2656,7 +_,7 @@
case 2001:
BlockState blockstate = Block.m_49803_(p_234307_);
if (!blockstate.m_60795_()) {
- SoundType soundtype = blockstate.m_60827_();
+ SoundType soundtype = blockstate.getSoundType(this.f_109465_, p_234306_, null);
+ SoundType soundtype = blockstate.getSoundType(this.f_109465_, p_234306_, null);
this.f_109465_.m_245747_(p_234306_, soundtype.m_56775_(), SoundSource.BLOCKS, (soundtype.m_56773_() + 1.0F) / 2.0F, soundtype.m_56774_() * 0.8F, false);
}
@@ -2751,7 +_,7 @@
break;
case 3002:
if (p_234307_ >= 0 && p_234307_ < Direction.Axis.f_122448_.length) {
- ParticleUtils.m_144967_(Direction.Axis.f_122448_[p_234307_], this.f_109465_, p_234306_, 0.125D, ParticleTypes.f_175830_, UniformInt.m_146622_(10, 19));
+ this.playStreamingMusic(((RecordItem)Item.m_41445_(p_234307_)).m_43051_(), p_234306_, (RecordItem) Item.m_41445_(p_234307_));
} else {
ParticleUtils.m_216313_(this.f_109465_, p_234306_, ParticleTypes.f_175830_, UniformInt.m_146622_(3, 5));
}
@@ -2875,7 +_,7 @@
} else {
int i = p_109538_.m_45517_(LightLayer.SKY, p_109540_);
@@ -1,21 +1,30 @@
--- a/net/minecraft/client/renderer/RenderType.java
+++ b/net/minecraft/client/renderer/RenderType.java
@@ -308,7 +_,7 @@
}
public static RenderType m_110497_(ResourceLocation p_110498_) {
- return f_173173_.apply(p_110498_);
+ return net.minecraftforge.client.ForgeRenderTypes.getText(p_110498_);
}
public static RenderType m_269058_() {
@@ -316,19 +_,19 @@
}
public static RenderType m_173237_(ResourceLocation p_173238_) {
- return f_173174_.apply(p_173238_);
+ return net.minecraftforge.client.ForgeRenderTypes.getText(p_173238_);
+ return net.minecraftforge.client.ForgeRenderTypes.getTextIntensity(p_173238_);
}
public static RenderType m_181444_(ResourceLocation p_181445_) {
- return f_181442_.apply(p_181445_);
+ return net.minecraftforge.client.ForgeRenderTypes.getTextIntensity(p_181445_);
+ return net.minecraftforge.client.ForgeRenderTypes.getTextPolygonOffset(p_181445_);
}
public static RenderType m_181446_(ResourceLocation p_181447_) {
- return f_181443_.apply(p_181447_);
+ return net.minecraftforge.client.ForgeRenderTypes.getTextPolygonOffset(p_181447_);
+ return net.minecraftforge.client.ForgeRenderTypes.getTextIntensityPolygonOffset(p_181447_);
}
public static RenderType m_110500_(ResourceLocation p_110501_) {
@@ -16,10 +16,11 @@
}
public static Material m_173381_(WoodType p_173382_) {
@@ -209,5 +_,13 @@
@@ -208,6 +_,23 @@
case SINGLE:
default:
return p_110773_;
}
+ }
+ }
+
+ /**
@@ -28,5 +29,14 @@
+ public static void addWoodType(WoodType woodType) {
+ f_110743_.put(woodType, m_173385_(woodType));
+ f_244291_.put(woodType, m_245275_(woodType));
+ }
+
+ static {
+ if (net.minecraftforge.fml.ModLoader.isLoadingStateValid() && !net.minecraftforge.fml.ModLoader.get().hasCompletedState("LOAD_REGISTRIES")) {
+ com.mojang.logging.LogUtils.getLogger().error(
+ "net.minecraft.client.renderer.Sheets loaded too early, modded registry-based materials may not work correctly",
+ new IllegalStateException("net.minecraft.client.renderer.Sheets loaded too early")
+ );
}
}
}
@@ -0,0 +1,11 @@
--- a/net/minecraft/client/renderer/culling/Frustum.java
+++ b/net/minecraft/client/renderer/culling/Frustum.java
@@ -59,6 +_,8 @@
}
public boolean m_113029_(AABB p_113030_) {
+ // FORGE: exit early for infinite bounds, these would otherwise fail in the intersection test at certain camera angles (GH-9321)
+ if (p_113030_.equals(net.minecraftforge.common.extensions.IForgeBlockEntity.INFINITE_EXTENT_AABB)) return true;
return this.m_113006_(p_113030_.f_82288_, p_113030_.f_82289_, p_113030_.f_82290_, p_113030_.f_82291_, p_113030_.f_82292_, p_113030_.f_82293_);
}
@@ -64,7 +64,7 @@
}
p_275269_.m_85849_();
+ net.minecraftforge.client.ItemDecoratorHandler.of(p_275590_).render(p_275652_, p_275590_, p_275202_, p_275508_, 0);
+ net.minecraftforge.client.ItemDecoratorHandler.of(p_275590_).render(p_275269_, p_275652_, p_275590_, p_275202_, p_275508_);
}
}
@@ -16,11 +16,11 @@
float f2 = (float)(i & 255) / 255.0F;
- this.m_117106_(p_117119_, p_117120_, p_117123_, armoritem, flag, p_117124_, flag1, f, f1, f2, (String)null);
- this.m_117106_(p_117119_, p_117120_, p_117123_, armoritem, flag, p_117124_, flag1, 1.0F, 1.0F, 1.0F, "overlay");
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag1, model, f, f1, f2, this.getArmorResource(p_117121_, itemstack, p_117122_, null));
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag1, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(p_117121_, itemstack, p_117122_, "overlay"));
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag, model, f, f1, f2, this.getArmorResource(p_117121_, itemstack, p_117122_, null));
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(p_117121_, itemstack, p_117122_, "overlay"));
} else {
- this.m_117106_(p_117119_, p_117120_, p_117123_, armoritem, flag, p_117124_, flag1, 1.0F, 1.0F, 1.0F, (String)null);
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag1, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(p_117121_, itemstack, p_117122_, null));
+ this.renderModel(p_117119_, p_117120_, p_117123_, flag, model, 1.0F, 1.0F, 1.0F, this.getArmorResource(p_117121_, itemstack, p_117122_, null));
}
if (p_117121_.f_19853_.m_246046_().m_245372_(FeatureFlags.f_244168_)) {
@@ -30,15 +30,6 @@
}
public void m_246368_(int p_248864_) {
@@ -70,7 +_,7 @@
}
}
- int m_245088_() {
+ private int m_245088_() {
return this.f_244575_ != null ? this.f_244575_.f_243714_.size() : 1;
}
@@ -124,6 +_,9 @@
void m_247381_(int p_248895_, int p_250245_, int p_250458_, int p_251337_, NativeImage[] p_248825_) {
@@ -13,7 +13,7 @@
friendlybytebuf.m_130130_(0);
friendlybytebuf.writeBytes(p_129453_);
} else {
+ if (!DISABLE_PACKET_DEBUG && i > 2097152) {
+ if (!DISABLE_PACKET_DEBUG && i > net.minecraft.network.CompressionDecoder.f_182672_) {
+ p_129453_.markReaderIndex();
+ LOGGER.error("Attempted to send packet over maximum protocol size: {} > 2097152\nData:\n{}", i,
+ net.minecraftforge.logging.PacketDump.getContentDump(p_129453_));
@@ -32,13 +32,3 @@
}
if (flag1 && !advancementprogress.m_8193_()) {
@@ -253,6 +_,9 @@
Set<Advancement> set = new HashSet<>();
Set<ResourceLocation> set1 = new HashSet<>();
+ if (net.minecraftforge.common.ForgeConfig.SERVER.fixAdvancementLoading.get())
+ net.minecraftforge.common.AdvancementLoadFix.loadVisibility(this, this.f_135965_, this.f_263821_, this.f_263740_, this.f_135967_, advancement -> AdvancementVisibilityEvaluator.isVisible(advancement, adv -> m_135996_(adv).m_8193_()));
+ else
for(Advancement advancement : this.f_263821_) {
this.m_264265_(advancement, set, set1);
}
@@ -24,7 +24,7 @@
+ p_140384_.currentlyLoading = levelchunk; // Forge - bypass the future chain when getChunk is called, this prevents deadlocks.
levelchunk.m_156369_();
levelchunk.m_187958_(this.f_140133_);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.ChunkEvent.Load(levelchunk));
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.ChunkEvent.Load(levelchunk, !(protochunk instanceof ImposterProtoChunk)));
+ } finally {
+ p_140384_.currentlyLoading = null; // Forge - Stop bypassing the future chain.
+ }
@@ -9,7 +9,7 @@
+ if (event.isCanceled() || (!this.m_9295_() && event.getResult() == net.minecraftforge.eventbus.api.Event.Result.DENY)) {
+ return;
+ }
+ if (!this.f_9245_.canInteractWith(p_215120_, 1)) {
+ if (!this.f_9245_.canReach(p_215120_, 1.5)) { // Vanilla check is eye-to-center distance < 6, so padding is 6 - 4.5 = 1.5
this.m_215125_(p_215120_, false, p_215124_, "too far");
} else if (p_215120_.m_123342_() >= p_215123_) {
this.f_9245_.f_8906_.m_9829_(new ClientboundBlockUpdatePacket(p_215120_, this.f_9244_.m_8055_(p_215120_)));
@@ -0,0 +1,10 @@
--- a/net/minecraft/server/level/WorldGenRegion.java
+++ b/net/minecraft/server/level/WorldGenRegion.java
@@ -297,6 +_,7 @@
}
public boolean m_7967_(Entity p_9580_) {
+ if (p_9580_ instanceof net.minecraft.world.entity.Mob mob && mob.isSpawnCancelled()) return false;
int i = SectionPos.m_123171_(p_9580_.m_146903_());
int j = SectionPos.m_123171_(p_9580_.m_146907_());
this.m_6325_(i, j).m_6286_(p_9580_);
@@ -6,8 +6,8 @@
private static final int f_143608_ = 15000;
+ /**
+ * Forge: Deprecated in favor of range/reach attributes.
+ * @see net.minecraftforge.common.ForgeMod#REACH_DISTANCE
+ * @see net.minecraftforge.common.ForgeMod#ATTACK_RANGE
+ * @see net.minecraftforge.common.ForgeMod#BLOCK_REACH
+ * @see net.minecraftforge.common.ForgeMod#ENTITY_REACH
+ */
+ @Deprecated
public static final double f_215198_ = Mth.m_144952_(6.0D);
@@ -39,7 +39,7 @@
BlockPos blockpos = blockhitresult.m_82425_();
Vec3 vec31 = Vec3.m_82512_(blockpos);
- if (!(this.f_9743_.m_146892_().m_82557_(vec31) > f_215198_)) {
+ if (this.f_9743_.canInteractWith(blockpos, 3)) {
+ if (this.f_9743_.canReach(blockpos, 1.5)) { // Vanilla uses eye-to-center distance < 6, which implies a padding of 1.5
Vec3 vec32 = vec3.m_82546_(vec31);
double d0 = 1.0000001D;
if (Math.abs(vec32.m_7096_()) < 1.0000001D && Math.abs(vec32.m_7098_()) < 1.0000001D && Math.abs(vec32.m_7094_()) < 1.0000001D) {
@@ -68,18 +68,15 @@
this.m_243086_(playerchatmessage1);
}, p_248212_);
});
@@ -1435,9 +_,10 @@
@@ -1435,7 +_,7 @@
}
AABB aabb = entity.m_20191_();
- if (aabb.m_272282_(this.f_9743_.m_146892_()) < f_215198_) {
+ if (true) { //Forge: Perform distance checks below since interactions and attacks differ.
+ if (this.f_9743_.canReach(entity, 3)) { // Vanilla padding is 3.0 (distSq < 6.0 * 6.0)
p_9866_.m_179617_(new ServerboundInteractPacket.Handler() {
private void m_143678_(InteractionHand p_143679_, ServerGamePacketListenerImpl.EntityInteraction p_143680_) {
+ 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_);
if (itemstack.m_246617_(serverlevel.m_246046_())) {
ItemStack itemstack1 = itemstack.m_41777_();
@@ -1458,6 +_,8 @@
public void m_142143_(InteractionHand p_143682_, Vec3 p_143683_) {
@@ -89,15 +86,6 @@
return p_143687_.m_7111_(p_143686_, p_143683_, p_143688_);
});
}
@@ -1466,6 +_,8 @@
if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.f_9743_) {
ItemStack itemstack = ServerGamePacketListenerImpl.this.f_9743_.m_21120_(InteractionHand.MAIN_HAND);
if (itemstack.m_246617_(serverlevel.m_246046_())) {
+ //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3
+ if(ServerGamePacketListenerImpl.this.f_9743_.canHit(entity, 3))
ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity);
}
} else {
@@ -1670,6 +_,7 @@
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/damagesource/DamageSource.java
+++ b/net/minecraft/world/damagesource/DamageSource.java
@@ -32,7 +_,7 @@
return this.f_268569_ != this.f_268595_;
}
- public DamageSource(Holder<DamageType> p_270906_, @Nullable Entity p_270796_, @Nullable Entity p_270459_, @Nullable Vec3 p_270623_) {
+ private DamageSource(Holder<DamageType> p_270906_, @Nullable Entity p_270796_, @Nullable Entity p_270459_, @Nullable Vec3 p_270623_) {
this.f_268495_ = p_270906_;
this.f_268569_ = p_270459_;
this.f_268595_ = p_270796_;
@@ -48,14 +48,6 @@
}
@Nullable
@@ -380,6 +_,7 @@
public T m_262455_(ServerLevel p_262704_, @Nullable CompoundTag p_262603_, @Nullable Consumer<T> p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_) {
T t = this.m_262451_(p_262704_, p_262603_, p_262621_, p_262672_, p_262644_, p_262690_, p_262590_);
if (t != null) {
+ if (t instanceof net.minecraft.world.entity.Mob && net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((net.minecraft.world.entity.Mob) t, p_262704_, p_262672_.m_123341_(), p_262672_.m_123342_(), p_262672_.m_123343_(), null, p_262644_)) return null;
p_262704_.m_47205_(t);
}
@@ -600,14 +_,23 @@
}
@@ -5,7 +5,7 @@
import org.slf4j.Logger;
-public abstract class LivingEntity extends Entity implements Attackable {
+public abstract class LivingEntity extends Entity implements net.minecraftforge.common.extensions.IForgeLivingEntity {
+public abstract class LivingEntity extends Entity implements Attackable, net.minecraftforge.common.extensions.IForgeLivingEntity {
private static final Logger f_201943_ = LogUtils.getLogger();
private static final UUID f_20929_ = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D");
private static final UUID f_20959_ = UUID.fromString("87f46a96-686f-4796-b035-22e16ee9e038");
@@ -371,24 +371,14 @@
p_21241_ = this.m_21161_(p_21240_, p_21241_);
p_21241_ = this.m_6515_(p_21240_, p_21241_);
float f1 = Math.max(p_21241_ - this.m_6103_(), 0.0F);
@@ -1560,14 +_,16 @@
Entity entity = p_21240_.m_7639_();
if (entity instanceof ServerPlayer) {
ServerPlayer serverplayer = (ServerPlayer)entity;
- serverplayer.m_36222_(Stats.f_12929_, Math.round(f * 10.0F));
@@ -1564,6 +_,7 @@
}
+ ((ServerPlayer)p_21240_.m_7639_()).m_6278_(Stats.f_12988_.m_12902_(Stats.f_12929_), Math.round(f * 10.0F));
}
+ f1 = net.minecraftforge.common.ForgeHooks.onLivingDamage(this, p_21240_, f1);
if (f1 != 0.0F) {
float f2 = this.m_21223_();
this.m_21231_().m_19289_(p_21240_, f2, f1);
this.m_21153_(f2 - f1);
+ this.m_21153_(f1 - f2); // Forge: moved to fix MC-121048
this.m_7911_(this.m_6103_() - f1);
this.m_146850_(GameEvent.f_223706_);
}
@@ -1622,6 +_,8 @@
}
@@ -529,25 +519,37 @@
if (itemstack.m_150930_(Items.f_42741_) && ElytraItem.m_41140_(itemstack)) {
flag = true;
int i = this.f_20937_ + 1;
@@ -2786,8 +_,16 @@
@@ -2786,8 +_,11 @@
private void m_21329_() {
if (this.m_6117_()) {
- if (ItemStack.m_41746_(this.m_21120_(this.m_7655_()), this.f_20935_)) {
- this.f_20935_ = this.m_21120_(this.m_7655_());
+ ItemStack itemStack = this.m_21120_(this.m_7655_());
+ if (net.minecraftforge.common.ForgeHooks.canContinueUsing(this.f_20935_, itemStack)) this.f_20935_ = itemStack;
+ if (net.minecraftforge.common.ForgeHooks.canContinueUsing(this.f_20935_, itemStack)) {
+ this.f_20935_ = itemStack;
+ }
+ if (itemStack == this.f_20935_) {
+
+ if (!this.f_20935_.m_41619_()) {
+ f_20936_ = net.minecraftforge.event.ForgeEventFactory.onItemUseTick(this, f_20935_, f_20936_);
+ if (f_20936_ > 0)
+ f_20935_.onUsingTick(this, f_20936_);
+ }
+
this.m_142106_(this.f_20935_);
} else {
this.m_5810_();
@@ -2797,12 +_,15 @@
}
protected void m_142106_(ItemStack p_147201_) {
+ if (!p_147201_.m_41619_())
+ this.f_20936_ = net.minecraftforge.event.ForgeEventFactory.onItemUseTick(this, p_147201_, this.m_21212_());
+ if (this.m_21212_() > 0)
p_147201_.m_41731_(this.f_19853_, this, this.m_21212_());
if (this.m_21332_()) {
this.m_21137_(p_147201_, 5);
}
- if (--this.f_20936_ == 0 && !this.f_19853_.f_46443_ && !p_147201_.m_41781_()) {
+ if (--this.f_20936_ <= 0 && !this.f_19853_.f_46443_ && !p_147201_.m_41781_()) {
this.m_8095_();
}
@@ -2810,7 +_,7 @@
private boolean m_21332_() {
@@ -1,5 +1,15 @@
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -116,6 +_,9 @@
private CompoundTag f_21359_;
private BlockPos f_21360_ = BlockPos.f_121853_;
private float f_21341_ = -1.0F;
+ @Nullable
+ private MobSpawnType spawnType;
+ private boolean spawnCancelled = false;
protected Mob(EntityType<? extends Mob> p_21368_, Level p_21369_) {
super(p_21368_, p_21369_);
@@ -224,7 +_,11 @@
}
@@ -13,6 +23,31 @@
}
public boolean m_6549_(EntityType<?> p_21399_) {
@@ -422,6 +_,9 @@
p_21484_.m_128379_("NoAI", this.m_21525_());
}
+ if (this.spawnType != null) {
+ p_21484_.m_128359_("forge:spawn_type", this.spawnType.name());
+ }
}
public void m_7378_(CompoundTag p_21450_) {
@@ -474,6 +_,14 @@
}
this.m_21557_(p_21450_.m_128471_("NoAI"));
+
+ if (p_21450_.m_128441_("forge:spawn_type")) {
+ try {
+ this.spawnType = MobSpawnType.valueOf(p_21450_.m_128461_("forge:spawn_type"));
+ } catch (Exception ex) {
+ p_21450_.m_128473_("forge:spawn_type");
+ }
+ }
}
protected void m_7625_(DamageSource p_21389_, boolean p_21390_) {
@@ -513,9 +_,9 @@
public void m_8107_() {
super.m_8107_();
@@ -28,7 +63,7 @@
this.m_146870_();
} else if (!this.m_21532_() && !this.m_8023_()) {
Entity entity = this.f_19853_.m_45930_(this, -1.0D);
+ net.minecraftforge.eventbus.api.Event.Result result = net.minecraftforge.event.ForgeEventFactory.canEntityDespawn(this);
+ net.minecraftforge.eventbus.api.Event.Result result = net.minecraftforge.event.ForgeEventFactory.canEntityDespawn(this, (ServerLevel) this.f_19853_);
+ if (result == net.minecraftforge.eventbus.api.Event.Result.DENY) {
+ f_20891_ = 0;
+ entity = null;
@@ -39,7 +74,32 @@
if (entity != null) {
double d0 = entity.m_20280_(this);
int i = this.m_6095_().m_20674_().m_21611_();
@@ -1410,13 +_,23 @@
@@ -1020,6 +_,16 @@
}
+ /**
+ * Forge: Override-Only, call via ForgeEventFactory.onFinalizeSpawn.<br>
+ * Overrides are allowed. Do not wrap super calls within override (as that will cause stack overflows).<br>
+ * Vanilla calls are replaced with a transformer, and are not visible in source.<br>
+ * <p>
+ * Be certain to either call super.finalizeSpawn or set the {@link #spawnType} field from within your override.
+ * @see {@link net.minecraftforge.event.ForgeEventFactory#onFinalizeSpawn onFinalizeSpawn} for additional documentation.
+ */
+ @Deprecated
+ @org.jetbrains.annotations.ApiStatus.OverrideOnly
@Nullable
public SpawnGroupData m_6518_(ServerLevelAccessor p_21434_, DifficultyInstance p_21435_, MobSpawnType p_21436_, @Nullable SpawnGroupData p_21437_, @Nullable CompoundTag p_21438_) {
RandomSource randomsource = p_21434_.m_213780_();
@@ -1030,6 +_,7 @@
this.m_21559_(false);
}
+ this.spawnType = p_21436_;
return p_21437_;
}
@@ -1410,15 +_,25 @@
return false;
}
@@ -56,11 +116,54 @@
this.m_20256_(this.m_20184_().m_82520_(0.0D, 0.3D, 0.0D));
}
+ }
+
}
+ @Override
+ public void jumpInFluid(net.minecraftforge.fluids.FluidType type) {
+ this.jumpInLiquidInternal(() -> super.jumpInFluid(type));
}
+ }
+
public void m_147272_() {
this.m_262441_((p_262562_) -> {
return true;
@@ -1442,5 +_,40 @@
public ItemStack m_142340_() {
SpawnEggItem spawneggitem = SpawnEggItem.m_43213_(this.m_6095_());
return spawneggitem == null ? null : new ItemStack(spawneggitem);
+ }
+
+ /**
+ * Returns the type of spawn that created this mob, if applicable.
+ * If it could not be determined, this will return null.
+ * <p>
+ * This is set via {@link Mob#finalizeSpawn}, so you should not call this from within that method, instead using the parameter.
+ */
+ @Nullable
+ public final MobSpawnType getSpawnType() {
+ return this.spawnType;
+ }
+
+ /**
+ * This method exists so that spawns can be cancelled from the {@link net.minecraftforge.event.entity.living.MobSpawnEvent.FinalizeSpawn FinalizeSpawnEvent}
+ * without needing to hook up an additional handler for the {@link net.minecraftforge.event.entity.EntityJoinLevelEvent EntityJoinLevelEvent}.
+ * @return if this mob will be blocked from spawning during {@link Level#addFreshEntity(Entity)}
+ * @apiNote Not public-facing API.
+ */
+ @org.jetbrains.annotations.ApiStatus.Internal
+ public final boolean isSpawnCancelled() {
+ return this.spawnCancelled;
+ }
+
+ /**
+ * Marks this mob as being disallowed to spawn during {@link Level#addFreshEntity(Entity)}.<p>
+ * @throws UnsupportedOperationException if this entity has already been {@link Entity#isAddedToWorld() added to the world}.
+ * @apiNote Not public-facing API.
+ */
+ @org.jetbrains.annotations.ApiStatus.Internal
+ public final void setSpawnCancelled(boolean cancel) {
+ if (this.isAddedToWorld()) {
+ throw new UnsupportedOperationException("Late invocations of Mob#setSpawnCancelled are not permitted.");
+ }
+ this.spawnCancelled = cancel;
}
}
@@ -7,7 +7,7 @@
+ /**
+ * The maximum age of this EntityItem. The item is expired once this is reached.
+ */
+ public int lifespan = 6000;
+ public int lifespan = ItemEntity.f_149659_;
public ItemEntity(EntityType<? extends ItemEntity> p_31991_, Level p_31992_) {
super(p_31991_, p_31992_);
@@ -15,10 +15,18 @@
this.m_6034_(p_149664_, p_149665_, p_149666_);
this.m_20334_(p_149668_, p_149669_, p_149670_);
this.m_32045_(p_149667_);
+ this.lifespan = (p_149667_.m_41720_() == null ? 6000 : p_149667_.getEntityLifespan(p_149663_));
+ this.lifespan = (p_149667_.m_41720_() == null ? ItemEntity.f_149659_ : p_149667_.getEntityLifespan(p_149663_));
}
private ItemEntity(ItemEntity p_31994_) {
@@ -66,6 +_,7 @@
this.m_20359_(p_31994_);
this.f_31985_ = p_31994_.f_31985_;
this.f_31983_ = p_31994_.f_31983_;
+ this.lifespan = p_31994_.lifespan;
}
public boolean m_213854_() {
@@ -94,6 +_,7 @@
}
@@ -46,7 +54,7 @@
}
this.m_20256_(this.m_20184_().m_82542_((double)f1, 0.98D, (double)f1));
@@ -158,7 +_,14 @@
@@ -158,7 +_,16 @@
}
}
@@ -54,11 +62,13 @@
+ ItemStack item = this.m_32055_();
+ if (!this.f_19853_.f_46443_ && this.f_31985_ >= lifespan) {
+ int hook = net.minecraftforge.event.ForgeEventFactory.onItemExpire(this, item);
+ if (hook < 0) this.m_146870_();
+ else this.lifespan += hook;
+ if (hook < 0) {
+ this.m_146870_();
+ } else {
+ this.lifespan += hook;
+ }
+ }
+
+ if (item.m_41619_()) {
+ if (item.m_41619_() && !this.m_213877_()) {
this.m_146870_();
}
@@ -71,14 +81,6 @@
} else {
return !p_32028_.m_41782_() || p_32028_.m_41783_().equals(p_32027_.m_41783_());
}
@@ -249,6 +_,7 @@
}
public boolean m_6469_(DamageSource p_32013_, float p_32014_) {
+ if (this.f_19853_.f_46443_ || this.m_213877_()) return false; //Forge: Fixes MC-53850
if (this.m_6673_(p_32013_)) {
return false;
} else if (!this.m_32055_().m_41619_() && this.m_32055_().m_150930_(Items.f_42686_) && p_32013_.m_269533_(DamageTypeTags.f_268415_)) {
@@ -262,7 +_,7 @@
this.f_31987_ = (int)((float)this.f_31987_ - p_32014_);
this.m_146852_(GameEvent.f_223706_, p_32013_.m_7639_());
@@ -92,19 +94,21 @@
p_32050_.m_128376_("Health", (short)this.f_31987_);
p_32050_.m_128376_("Age", (short)this.f_31985_);
p_32050_.m_128376_("PickupDelay", (short)this.f_31986_);
+ p_32050_.m_128405_("Lifespan", lifespan);
+ p_32050_.m_128405_("Lifespan", this.lifespan);
if (this.f_31988_ != null) {
p_32050_.m_128362_("Thrower", this.f_31988_);
}
@@ -294,6 +_,7 @@
@@ -294,6 +_,9 @@
if (p_32034_.m_128441_("PickupDelay")) {
this.f_31986_ = p_32034_.m_128448_("PickupDelay");
}
+ if (p_32034_.m_128441_("Lifespan")) lifespan = p_32034_.m_128451_("Lifespan");
+ if (p_32034_.m_128441_("Lifespan")) {
+ this.lifespan = p_32034_.m_128451_("Lifespan");
+ }
if (p_32034_.m_128403_("Owner")) {
this.f_265881_ = p_32034_.m_128342_("Owner");
@@ -313,10 +_,18 @@
@@ -313,10 +_,17 @@
public void m_6123_(Player p_32040_) {
if (!this.f_19853_.f_46443_) {
@@ -113,13 +117,12 @@
Item item = itemstack.m_41720_();
int i = itemstack.m_41613_();
- if (this.f_31986_ == 0 && (this.f_265881_ == null || this.f_265881_.equals(p_32040_.m_20148_())) && p_32040_.m_150109_().m_36054_(itemstack)) {
+
+ int hook = net.minecraftforge.event.ForgeEventFactory.onItemPickup(this, p_32040_);
+ if (hook < 0) return;
+
+ ItemStack copy = itemstack.m_41777_();
+ if (this.f_31986_ == 0 && (this.m_19749_() == null || lifespan - this.f_31985_ <= 200 || this.m_19749_().m_20148_().equals(p_32040_.m_20148_())) && (hook == 1 || i <= 0 || p_32040_.m_150109_().m_36054_(itemstack))) {
+ copy.m_41764_(copy.m_41613_() - m_32055_().m_41613_());
+ if (this.f_31986_ == 0 && (this.f_265881_ == null || this.f_265881_.equals(p_32040_.m_20148_())) && (hook == 1 || i <= 0 || p_32040_.m_150109_().m_36054_(itemstack))) {
+ i = copy.m_41613_() - itemstack.m_41613_();
+ copy.m_41764_(i);
+ net.minecraftforge.event.ForgeEventFactory.firePlayerItemPickupEvent(p_32040_, this, copy);
p_32040_.m_7938_(this, i);
if (itemstack.m_41619_()) {
@@ -140,7 +143,7 @@
public void m_32065_() {
this.m_32062_();
- this.f_31985_ = 5999;
+ this.f_31985_ = m_32055_().getEntityLifespan(f_19853_) - 1;
+ this.f_31985_ = m_32055_().getEntityLifespan(this.f_19853_) - 1;
}
public float m_32008_(float p_32009_) {
@@ -1,11 +1,10 @@
--- a/net/minecraft/world/entity/npc/CatSpawner.java
+++ b/net/minecraft/world/entity/npc/CatSpawner.java
@@ -86,8 +_,9 @@
@@ -86,8 +_,8 @@
if (cat == null) {
return 0;
} else {
+ cat.m_20035_(p_35334_, 0.0F, 0.0F); // Fix MC-147659: Some witch huts spawn the incorrect cat
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(cat, p_35335_, p_35334_.m_123341_(), p_35334_.m_123342_(), p_35334_.m_123343_(), null, MobSpawnType.NATURAL) == -1) return 0;
cat.m_6518_(p_35335_, p_35335_.m_6436_(p_35334_), MobSpawnType.NATURAL, (SpawnGroupData)null, (CompoundTag)null);
- cat.m_20035_(p_35334_, 0.0F, 0.0F);
p_35335_.m_47205_(cat);
@@ -1,10 +1,6 @@
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -126,14 +_,14 @@
if (this.f_35974_.get(j).m_41619_()) {
return j;
}
- }
@@ -130,7 +_,7 @@
for(int k = 0; k < 9; ++k) {
int l = (this.f_35977_ + k) % 9;
@@ -13,10 +9,6 @@
return l;
}
}
+ }
return this.f_35977_;
}
@@ -178,7 +_,8 @@
int i = p_36049_.m_41613_();
ItemStack itemstack = this.m_8020_(p_36048_);
@@ -25,7 +25,7 @@
public static AttributeSupplier.Builder m_36340_() {
- return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double)0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_);
+ return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double) 0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_).m_22266_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22266_(Attributes.f_22282_).m_22266_(net.minecraftforge.common.ForgeMod.ATTACK_RANGE.get());
+ return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double) 0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_).m_22266_(net.minecraftforge.common.ForgeMod.BLOCK_REACH.get()).m_22266_(Attributes.f_22282_).m_22266_(net.minecraftforge.common.ForgeMod.ENTITY_REACH.get());
}
protected void m_8097_() {
@@ -202,12 +202,13 @@
protected Vec3 m_5763_(Vec3 p_36201_, MoverType p_36202_) {
if (!this.f_36077_.f_35935_ && p_36201_.f_82480_ <= 0.0D && (p_36202_ == MoverType.SELF || p_36202_ == MoverType.PLAYER) && this.m_36343_() && this.m_36386_()) {
double d0 = p_36201_.f_82479_;
@@ -1047,10 +_,11 @@
@@ -1046,11 +_,13 @@
return p_36201_;
}
+ // Forge: Don't update this method to use IForgeEntity#getStepHeight() - https://github.com/MinecraftForge/MinecraftForge/issues/9376
private boolean m_36386_() {
- return this.f_19861_ || this.f_19789_ < this.m_274421_() && !this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(0.0D, (double)(this.f_19789_ - this.m_274421_()), 0.0D));
+ return this.f_19861_ || this.f_19789_ < this.getStepHeight() && !this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(0.0D, (double)(this.f_19789_ - this.getStepHeight()), 0.0D));
return this.f_19861_ || this.f_19789_ < this.m_274421_() && !this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(0.0D, (double)(this.f_19789_ - this.m_274421_()), 0.0D));
}
public void m_5706_(Entity p_36347_) {
@@ -251,14 +252,15 @@
}
float f4 = 0.0F;
@@ -1120,8 +_,8 @@
@@ -1120,8 +_,9 @@
if (flag3) {
float f3 = 1.0F + EnchantmentHelper.m_44821_(this) * f;
- for(LivingEntity livingentity : this.f_19853_.m_45976_(LivingEntity.class, p_36347_.m_20191_().m_82377_(1.0D, 0.25D, 1.0D))) {
- if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.m_20280_(livingentity) < 9.0D) {
+ for(LivingEntity livingentity : this.f_19853_.m_45976_(LivingEntity.class, this.m_21120_(InteractionHand.MAIN_HAND).getSweepHitBox(this, p_36347_))) {
+ if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.canHit(livingentity, 0)) { // Original check was dist < 3, range is 3, so vanilla used padding=0
+ double entityReachSq = Mth.m_144952_(this.getEntityReach()); // Use entity reach instead of constant 9.0. Vanilla uses bottom center-to-center checks here, so don't update this to use canReach, since it uses closest-corner checks.
+ if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.m_20280_(livingentity) < entityReachSq) {
livingentity.m_147240_((double)0.4F, (double)Mth.m_14031_(this.m_146908_() * ((float)Math.PI / 180F)), (double)(-Mth.m_14089_(this.m_146908_() * ((float)Math.PI / 180F))));
livingentity.m_6469_(this.m_269291_().m_269075_(this), f3);
}
@@ -9,12 +9,14 @@
this.m_20095_();
}
@@ -186,7 +_,7 @@
@@ -186,7 +_,9 @@
}
}
- if (hitresult != null && !flag) {
+ if (hitresult != null && hitresult.m_6662_() != HitResult.Type.MISS && !flag && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, hitresult)) {
+ if (hitresult != null && hitresult.m_6662_() != HitResult.Type.MISS && !flag) {
+ if (net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, hitresult))
+ break;
this.m_6532_(hitresult);
this.f_19812_ = true;
}
@@ -1,10 +1,7 @@
--- a/net/minecraft/world/food/FoodData.java
+++ b/net/minecraft/world/food/FoodData.java
@@ -21,11 +_,18 @@
public void m_38707_(int p_38708_, float p_38709_) {
this.f_38696_ = Math.min(p_38708_ + this.f_38696_, 20);
@@ -23,9 +_,15 @@
this.f_38697_ = Math.min(this.f_38697_ + (float)p_38708_ * p_38709_ * 2.0F, (float)this.f_38696_);
+ this.f_38697_ = Math.min(this.f_38697_ + (float)p_38708_ * p_38709_ * 2.0F, (float)this.f_38696_);
}
+ // Use the LivingEntity sensitive version in favour of this.
@@ -13,13 +13,13 @@
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
+ return p_39607_.m_41763_() || p_39607_.m_150930_(Items.f_42690_) || p_39607_.m_41793_() || p_39607_.canGrindstoneRepair();
}
});
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
+ return p_39616_.m_41763_() || p_39616_.m_150930_(Items.f_42690_) || p_39616_.m_41793_() || p_39616_.canGrindstoneRepair();
}
});
this.m_38897_(new Slot(this.f_39559_, 2, 129, 34) {
@@ -67,6 +67,17 @@
if (!ItemStack.m_41728_(itemstack, itemstack1)) {
this.f_39559_.m_6836_(0, ItemStack.f_41583_);
this.m_38946_();
@@ -163,6 +_,10 @@
itemstack2 = flag3 ? itemstack : itemstack1;
}
+ // Forge: Skip the repair if the result would give an item stack with a count not normally obtainable
+ if (j > itemstack2.m_41741_())
+ this.f_39559_.m_6836_(0, ItemStack.f_41583_);
+ else
this.f_39559_.m_6836_(0, this.m_39579_(itemstack2, i, j));
}
@@ -175,7 +_,7 @@
for(Map.Entry<Enchantment, Integer> entry : map.entrySet()) {
@@ -0,0 +1,10 @@
--- a/net/minecraft/world/item/BrushItem.java
+++ b/net/minecraft/world/item/BrushItem.java
@@ -76,6 +_,7 @@
} else {
p_273619_.m_21253_();
}
+ super.m_5929_(p_273467_, p_273619_, p_273316_, p_273101_); //TODO: Remove in 1.20, this is only here to trigger Forge's old onUseingTick method
}
public void m_271895_(Level p_272701_, BlockHitResult p_273758_, BlockState p_272753_, Vec3 p_272912_) {
@@ -107,7 +107,7 @@
+ private final java.util.function.Supplier<? extends Fluid> fluidSupplier;
+ public Fluid getFluid() { return fluidSupplier.get(); }
+
+ private boolean canBlockContainFluid(Level worldIn, BlockPos posIn, BlockState blockstate)
+ protected boolean canBlockContainFluid(Level worldIn, BlockPos posIn, BlockState blockstate)
+ {
+ return blockstate.m_60734_() instanceof LiquidBlockContainer && ((LiquidBlockContainer)blockstate.m_60734_()).m_6044_(worldIn, posIn, blockstate, this.f_40687_);
}
@@ -0,0 +1,19 @@
--- a/net/minecraft/world/item/BundleItem.java
+++ b/net/minecraft/world/item/BundleItem.java
@@ -40,7 +_,7 @@
}
public boolean m_142207_(ItemStack p_150733_, Slot p_150734_, ClickAction p_150735_, Player p_150736_) {
- if (p_150735_ != ClickAction.SECONDARY) {
+ if (p_150733_.m_41613_() != 1 || p_150735_ != ClickAction.SECONDARY) {
return false;
} else {
ItemStack itemstack = p_150734_.m_7993_();
@@ -62,6 +_,7 @@
}
public boolean m_142305_(ItemStack p_150742_, ItemStack p_150743_, Slot p_150744_, ClickAction p_150745_, Player p_150746_, SlotAccess p_150747_) {
+ if (p_150742_.m_41613_() != 1) return false;
if (p_150745_ == ClickAction.SECONDARY && p_150744_.m_150651_(p_150746_)) {
if (p_150743_.m_41619_()) {
m_150780_(p_150742_).ifPresent((p_186347_) -> {
@@ -8,3 +8,11 @@
List<ItemStack> list = m_40941_(p_40891_);
float[] afloat = m_220023_(p_40889_.m_217043_());
@@ -304,6 +_,7 @@
p_40910_.m_6263_((Player)null, p_40911_.m_20185_(), p_40911_.m_20186_(), p_40911_.m_20189_(), soundevent1, SoundSource.PLAYERS, 0.5F, 1.0F);
}
}
+ super.m_5929_(p_40910_, p_40911_, p_40912_, p_40913_); //TODO: Remove in 1.20, this is only here to trigger Forge's old onUseingTick method
}
@@ -22,13 +22,16 @@
}
/** @deprecated */
@@ -108,6 +_,8 @@
return this.f_204113_;
@@ -109,8 +_,11 @@
}
+ /** @deprecated Forge: Use damage source sensitive version */
+ @Deprecated
public void m_5929_(Level p_41428_, LivingEntity p_41429_, ItemStack p_41430_, int p_41431_) {
+ p_41430_.onUsingTick(p_41429_, p_41431_);
}
+ /** @deprecated Forge: {@link net.minecraftforge.common.extensions.IForgeItem#onDestroyed(ItemEntity, DamageSource) Use damage source sensitive version} */
+ @Deprecated
public void m_142023_(ItemEntity p_150887_) {
}
@@ -134,9 +_,9 @@
@@ -109,7 +112,7 @@
float f7 = f2 * f4;
- double d0 = 5.0D;
- Vec3 vec31 = vec3.m_82520_((double)f6 * 5.0D, (double)f5 * 5.0D, (double)f7 * 5.0D);
+ double d0 = p_41437_.getReachDistance();
+ double d0 = p_41437_.getBlockReach();
+ Vec3 vec31 = vec3.m_82520_((double)f6 * d0, (double)f5 * d0, (double)f7 * d0);
return p_41436_.m_45547_(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, p_41438_, p_41437_));
}
@@ -248,7 +248,7 @@
this.m_41720_().m_5929_(p_41732_, p_41733_, this, p_41734_);
}
+ /** @deprecated Forge: Use damage source sensitive version */
+ /** @deprecated Forge: {@link net.minecraftforge.common.extensions.IForgeItemStack#onDestroyed(ItemEntity, DamageSource) Use damage source sensitive version} */
+ @Deprecated
public void m_150924_(ItemEntity p_150925_) {
this.m_41720_().m_142023_(p_150925_);
@@ -1,21 +1,18 @@
--- a/net/minecraft/world/level/BaseSpawner.java
+++ b/net/minecraft/world/level/BaseSpawner.java
@@ -131,11 +_,15 @@
entity.m_7678_(entity.m_20185_(), entity.m_20186_(), entity.m_20189_(), randomsource.m_188501_() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob mob = (Mob)entity;
+ net.minecraftforge.eventbus.api.Event.Result res = net.minecraftforge.event.ForgeEventFactory.canEntitySpawn(mob, p_151312_, (float)entity.m_20185_(), (float)entity.m_20186_(), (float)entity.m_20189_(), this, MobSpawnType.SPAWNER);
+ if (res == net.minecraftforge.eventbus.api.Event.Result.DENY) continue;
+ if (res == net.minecraftforge.eventbus.api.Event.Result.DEFAULT)
if (spawndata.m_186574_().isEmpty() && !mob.m_5545_(p_151312_, MobSpawnType.SPAWNER) || !mob.m_6914_(p_151312_)) {
@@ -135,8 +_,10 @@
continue;
}
if (spawndata.m_186567_().m_128440_() == 1 && spawndata.m_186567_().m_128425_("id", 8)) {
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, (LevelAccessor)p_151312_, (float)entity.m_20185_(), (float)entity.m_20186_(), (float)entity.m_20189_(), this, MobSpawnType.SPAWNER))
((Mob)entity).m_6518_(p_151312_, p_151312_.m_6436_(entity.m_20183_()), MobSpawnType.SPAWNER, (SpawnGroupData)null, (CompoundTag)null);
- if (spawndata.m_186567_().m_128440_() == 1 && spawndata.m_186567_().m_128425_("id", 8)) {
- ((Mob)entity).m_6518_(p_151312_, p_151312_.m_6436_(entity.m_20183_()), MobSpawnType.SPAWNER, (SpawnGroupData)null, (CompoundTag)null);
+ // Forge: Patch in the spawn event for spawners so it may be fired unconditionally, instead of only when vanilla normally would trigger it.
+ var event = net.minecraftforge.event.ForgeEventFactory.onFinalizeSpawnSpawner(mob, p_151312_, p_151312_.m_6436_(entity.m_20183_()), null, compoundtag, this);
+ if (event != null && spawndata.m_186567_().m_128440_() == 1 && spawndata.m_186567_().m_128425_("id", 8)) {
+ ((Mob)entity).m_6518_(p_151312_, event.getDifficulty(), event.getSpawnType(), event.getSpawnData(), event.getSpawnTag());
}
}
@@ -283,4 +_,12 @@
public double m_45474_() {
return this.f_45446_;
@@ -17,16 +17,7 @@
if (mobcategory != MobCategory.MISC) {
BlockPos blockpos = entity.m_20183_();
p_186527_.m_47103_(ChunkPos.m_151388_(blockpos), (p_275163_) -> {
@@ -171,13 +_,15 @@
}
mob.m_7678_(d0, (double)i, d1, p_47040_.f_46441_.m_188501_() * 360.0F, 0.0F);
- if (m_46991_(p_47040_, mob, d2)) {
+ int canSpawn = net.minecraftforge.common.ForgeHooks.canEntitySpawn(mob, p_47040_, d0, i, d1, null, MobSpawnType.NATURAL);
+ if (canSpawn != -1 && (canSpawn == 1 || m_46991_(p_47040_, mob, d2))) {
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, (LevelAccessor) p_47040_, (float)d0, (float)i, (float)d1, null, MobSpawnType.NATURAL))
spawngroupdata = mob.m_6518_(p_47040_, p_47040_.m_6436_(mob.m_20183_()), MobSpawnType.NATURAL, spawngroupdata, (CompoundTag)null);
++j;
@@ -177,7 +_,7 @@
++l1;
p_47040_.m_47205_(mob);
p_47044_.m_47100_(mob, p_47041_);
@@ -75,11 +66,3 @@
}
}
@@ -366,6 +_,7 @@
entity.m_7678_(d0, (double)blockpos.m_123342_(), d1, p_220454_.m_188501_() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob mob = (Mob)entity;
+ if (net.minecraftforge.common.ForgeHooks.canEntitySpawn(mob, p_220451_, d0, blockpos.m_123342_(), d1, null, MobSpawnType.CHUNK_GENERATION) == -1) continue;
if (mob.m_5545_(p_220451_, MobSpawnType.CHUNK_GENERATION) && mob.m_6914_(p_220451_)) {
spawngroupdata = mob.m_6518_(p_220451_, p_220451_.m_6436_(mob.m_20183_()), MobSpawnType.CHUNK_GENERATION, spawngroupdata, (CompoundTag)null);
p_220451_.m_47205_(mob);
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -53,7 +_,7 @@
private final int f_244105_;
private final boolean f_243959_;
- public ButtonBlock(BlockBehaviour.Properties p_273290_, BlockSetType p_273462_, int p_273212_, boolean p_272786_) {
+ protected ButtonBlock(BlockBehaviour.Properties p_273290_, BlockSetType p_273462_, int p_273212_, boolean p_272786_) {
super(p_273290_.m_60918_(p_273462_.f_271136_()));
this.f_271519_ = p_273462_;
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_54117_, Direction.NORTH).m_61124_(f_51045_, Boolean.valueOf(false)).m_61124_(f_53179_, AttachFace.WALL));
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -30,7 +_,7 @@
private static final DirectionProperty f_271251_ = BlockStateProperties.f_61374_;
private static final BooleanProperty f_271222_ = BlockStateProperties.f_61362_;
- public DecoratedPotBlock(BlockBehaviour.Properties p_273064_) {
+ protected DecoratedPotBlock(BlockBehaviour.Properties p_273064_) {
super(p_273064_);
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_271251_, Direction.NORTH).m_61124_(f_271222_, Boolean.valueOf(false)));
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/DoorBlock.java
+++ b/net/minecraft/world/level/block/DoorBlock.java
@@ -48,7 +_,7 @@
protected static final VoxelShape f_52734_ = Block.m_49796_(0.0D, 0.0D, 0.0D, 3.0D, 16.0D, 16.0D);
private final BlockSetType f_271255_;
- public DoorBlock(BlockBehaviour.Properties p_273303_, BlockSetType p_272854_) {
+ protected DoorBlock(BlockBehaviour.Properties p_273303_, BlockSetType p_272854_) {
super(p_273303_.m_60918_(p_272854_.f_271136_()));
this.f_271255_ = p_272854_;
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_52726_, Direction.NORTH).m_61124_(f_52727_, Boolean.valueOf(false)).m_61124_(f_52728_, DoorHingeSide.LEFT).m_61124_(f_52729_, Boolean.valueOf(false)).m_61124_(f_52730_, DoubleBlockHalf.LOWER));
@@ -0,0 +1,40 @@
--- a/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/net/minecraft/world/level/block/FenceGateBlock.java
@@ -41,11 +_,16 @@
protected static final VoxelShape f_53351_ = Shapes.m_83110_(Block.m_49796_(7.0D, 5.0D, 0.0D, 9.0D, 16.0D, 2.0D), Block.m_49796_(7.0D, 5.0D, 14.0D, 9.0D, 16.0D, 16.0D));
protected static final VoxelShape f_53352_ = Shapes.m_83110_(Block.m_49796_(0.0D, 2.0D, 7.0D, 2.0D, 13.0D, 9.0D), Block.m_49796_(14.0D, 2.0D, 7.0D, 16.0D, 13.0D, 9.0D));
protected static final VoxelShape f_53353_ = Shapes.m_83110_(Block.m_49796_(7.0D, 2.0D, 0.0D, 9.0D, 13.0D, 2.0D), Block.m_49796_(7.0D, 2.0D, 14.0D, 9.0D, 13.0D, 16.0D));
- private final WoodType f_271446_;
+ private final net.minecraft.sounds.SoundEvent openSound;
+ private final net.minecraft.sounds.SoundEvent closeSound;
public FenceGateBlock(BlockBehaviour.Properties p_273352_, WoodType p_273340_) {
- super(p_273352_.m_60918_(p_273340_.f_271317_()));
- this.f_271446_ = p_273340_;
+ this(p_273352_.m_60918_(p_273340_.f_271317_()), p_273340_.f_271162_(), p_273340_.f_271365_());
+ }
+ public FenceGateBlock(BlockBehaviour.Properties props, net.minecraft.sounds.SoundEvent openSound, net.minecraft.sounds.SoundEvent closeSound) {
+ super(props);
+ this.openSound = openSound;
+ this.closeSound = closeSound;
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_53341_, Boolean.valueOf(false)).m_61124_(f_53342_, Boolean.valueOf(false)).m_61124_(f_53343_, Boolean.valueOf(false)));
}
@@ -133,7 +_,7 @@
}
boolean flag = p_53365_.m_61143_(f_53341_);
- p_53366_.m_5594_(p_53368_, p_53367_, flag ? this.f_271446_.f_271162_() : this.f_271446_.f_271365_(), SoundSource.BLOCKS, 1.0F, p_53366_.m_213780_().m_188501_() * 0.1F + 0.9F);
+ p_53366_.m_5594_(p_53368_, p_53367_, flag ? this.openSound : this.closeSound, SoundSource.BLOCKS, 1.0F, p_53366_.m_213780_().m_188501_() * 0.1F + 0.9F);
p_53366_.m_142346_(p_53368_, flag ? GameEvent.f_157796_ : GameEvent.f_157793_, p_53367_);
return InteractionResult.m_19078_(p_53366_.f_46443_);
}
@@ -144,7 +_,7 @@
if (p_53372_.m_61143_(f_53342_) != flag) {
p_53373_.m_7731_(p_53374_, p_53372_.m_61124_(f_53342_, Boolean.valueOf(flag)).m_61124_(f_53341_, Boolean.valueOf(flag)), 2);
if (p_53372_.m_61143_(f_53341_) != flag) {
- p_53373_.m_5594_((Player)null, p_53374_, flag ? this.f_271446_.f_271162_() : this.f_271446_.f_271365_(), SoundSource.BLOCKS, 1.0F, p_53373_.m_213780_().m_188501_() * 0.1F + 0.9F);
+ p_53373_.m_5594_((Player)null, p_53374_, flag ? this.openSound : this.closeSound, SoundSource.BLOCKS, 1.0F, p_53373_.m_213780_().m_188501_() * 0.1F + 0.9F);
p_53373_.m_142346_((Entity)null, flag ? GameEvent.f_157796_ : GameEvent.f_157793_, p_53374_);
}
}
@@ -61,7 +61,7 @@
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
for(int l = -1; l <= 1; ++l) {
@@ -205,29 +_,28 @@
@@ -205,28 +_,27 @@
return p_53429_.m_46758_(p_53430_) || p_53429_.m_46758_(p_53430_.m_122024_()) || p_53429_.m_46758_(p_53430_.m_122029_()) || p_53429_.m_46758_(p_53430_.m_122012_()) || p_53429_.m_46758_(p_53430_.m_122019_());
}
@@ -82,26 +82,26 @@
- if (p_221154_.m_188503_(p_221155_ + 10) < 5 && !p_221151_.m_46758_(p_221152_)) {
- int j = Math.min(p_221155_ + p_221154_.m_188503_(5) / 4, 15);
- p_221151_.m_7731_(p_221152_, this.m_53437_(p_221151_, p_221152_, j), 3);
- } else {
- p_221151_.m_7471_(p_221152_, false);
- }
+ private void tryCatchFire(Level p_53432_, BlockPos p_53433_, int p_53434_, RandomSource p_53435_, int p_53436_, Direction face) {
+ int i = p_53432_.m_8055_(p_53433_).getFlammability(p_53432_, p_53433_, face);
+ if (p_53435_.m_188503_(p_53434_) < i) {
+ BlockState blockstate = p_53432_.m_8055_(p_53433_);
+ if (p_53435_.m_188503_(p_53434_ + 10) < 5 && !p_53432_.m_46758_(p_53433_)) {
+ int j = Math.min(p_53434_ + p_53435_.m_188503_(5) / 4, 15);
+ p_53432_.m_7731_(p_53433_, this.m_53437_(p_53432_, p_53433_, j), 3);
} else {
- p_221151_.m_7471_(p_221152_, false);
+ p_53432_.m_7471_(p_53433_, false);
}
+ blockstate.onCaughtFire(p_53432_, p_53433_, face, null);
- Block block = blockstate.m_60734_();
- if (block instanceof TntBlock) {
- TntBlock.m_57433_(p_221151_, p_221152_);
- }
+ blockstate.onCaughtFire(p_53432_, p_53433_, face, null);
+ if (p_53435_.m_188503_(p_53434_ + 10) < 5 && !p_53432_.m_46758_(p_53433_)) {
+ int j = Math.min(p_53434_ + p_53435_.m_188503_(5) / 4, 15);
+ p_53432_.m_7731_(p_53433_, this.m_53437_(p_53432_, p_53433_, j), 3);
+ } else {
+ p_53432_.m_7471_(p_53433_, false);
}
}
}
@@ -239,7 +_,7 @@
private boolean m_53485_(BlockGetter p_53486_, BlockPos p_53487_) {
@@ -1,11 +1,13 @@
--- a/net/minecraft/world/level/block/FungusBlock.java
+++ b/net/minecraft/world/level/block/FungusBlock.java
@@ -52,6 +_,8 @@
@@ -52,7 +_,9 @@
public void m_214148_(ServerLevel p_221243_, RandomSource p_221244_, BlockPos p_221245_, BlockState p_221246_) {
this.m_255216_(p_221243_).ifPresent((p_256352_) -> {
- p_256352_.m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_221243_, p_221244_, p_221245_, p_256352_);
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY)) return;
p_256352_.m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
+ event.getFeature().m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
});
}
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/PinkPetalsBlock.java
+++ b/net/minecraft/world/level/block/PinkPetalsBlock.java
@@ -24,7 +_,7 @@
public static final DirectionProperty f_271347_ = BlockStateProperties.f_61374_;
public static final IntegerProperty f_271373_ = BlockStateProperties.f_271526_;
- public PinkPetalsBlock(BlockBehaviour.Properties p_273335_) {
+ protected PinkPetalsBlock(BlockBehaviour.Properties p_273335_) {
super(p_273335_);
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_271347_, Direction.NORTH).m_61124_(f_271373_, Integer.valueOf(1)));
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/PressurePlateBlock.java
+++ b/net/minecraft/world/level/block/PressurePlateBlock.java
@@ -17,7 +_,7 @@
public static final BooleanProperty f_55249_ = BlockStateProperties.f_61448_;
private final PressurePlateBlock.Sensitivity f_55250_;
- public PressurePlateBlock(PressurePlateBlock.Sensitivity p_273523_, BlockBehaviour.Properties p_273571_, BlockSetType p_273284_) {
+ protected PressurePlateBlock(PressurePlateBlock.Sensitivity p_273523_, BlockBehaviour.Properties p_273571_, BlockSetType p_273284_) {
super(p_273571_, p_273284_);
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_55249_, Boolean.valueOf(false)));
this.f_55250_ = p_273523_;
@@ -1,14 +1,5 @@
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -42,7 +_,7 @@
protected static final VoxelShape f_57523_ = Block.m_49796_(0.0D, 13.0D, 0.0D, 16.0D, 16.0D, 16.0D);
private final BlockSetType f_271458_;
- public TrapDoorBlock(BlockBehaviour.Properties p_273079_, BlockSetType p_272964_) {
+ protected TrapDoorBlock(BlockBehaviour.Properties p_273079_, BlockSetType p_272964_) {
super(p_273079_.m_60918_(p_272964_.f_271136_()));
this.f_271458_ = p_272964_;
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_54117_, Direction.NORTH).m_61124_(f_57514_, Boolean.valueOf(false)).m_61124_(f_57515_, Half.BOTTOM).m_61124_(f_57516_, Boolean.valueOf(false)).m_61124_(f_57517_, Boolean.valueOf(false)));
@@ -149,4 +_,17 @@
return super.m_7417_(p_57554_, p_57555_, p_57556_, p_57557_, p_57558_, p_57559_);
@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
+++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
@@ -15,7 +_,7 @@
public static final IntegerProperty f_58198_ = BlockStateProperties.f_61426_;
private final int f_58199_;
- public WeightedPressurePlateBlock(int p_273669_, BlockBehaviour.Properties p_273512_, BlockSetType p_272868_) {
+ protected WeightedPressurePlateBlock(int p_273669_, BlockBehaviour.Properties p_273512_, BlockSetType p_272868_) {
super(p_273512_, p_272868_);
this.m_49959_(this.f_49792_.m_61090_().m_61124_(f_58198_, Integer.valueOf(0)));
this.f_58199_ = p_273669_;
@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java
+++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java
@@ -104,6 +_,7 @@
}
patrollingmonster.m_6034_((double)p_224534_.m_123341_(), (double)p_224534_.m_123342_(), (double)p_224534_.m_123343_());
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(patrollingmonster, p_224533_, p_224534_.m_123341_(), p_224534_.m_123342_(), p_224534_.m_123343_(), null, MobSpawnType.PATROL) == -1) return false;
patrollingmonster.m_6518_(p_224533_, p_224533_.m_6436_(p_224534_), MobSpawnType.PATROL, (SpawnGroupData)null, (CompoundTag)null);
p_224533_.m_47205_(patrollingmonster);
return true;
@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -61,6 +_,10 @@
Phantom phantom = EntityType.f_20509_.m_20615_(p_64576_);
if (phantom != null) {
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) {
+ i--;
+ continue;
+ }
spawngroupdata = phantom.m_6518_(p_64576_, difficultyinstance, MobSpawnType.NATURAL, spawngroupdata, (CompoundTag)null);
p_64576_.m_47205_(phantom);
++i;
@@ -0,0 +1,22 @@
{
"item.bucket.empty_milk": {
"sounds": [
"item/bucket/empty1",
{
"name": "item/bucket/empty1",
"pitch": 0.9
},
"item/bucket/empty2",
"item/bucket/empty3"
],
"subtitle": "subtitles.item.bucket.empty"
},
"item.bucket.fill_milk": {
"sounds": [
"item/bucket/fill1",
"item/bucket/fill2",
"item/bucket/fill3"
],
"subtitle": "subtitles.item.bucket.fill"
}
}
@@ -5,6 +5,11 @@
"#forge:tools/pickaxes",
"#forge:tools/shovels",
"#forge:tools/hoes",
"#minecraft:swords",
"#minecraft:axes",
"#minecraft:pickaxes",
"#minecraft:shovels",
"#minecraft:hoes",
"#forge:tools/shields",
"#forge:tools/bows",
"#forge:tools/crossbows",
@@ -5,6 +5,7 @@
"minecraft:iron_axe",
"minecraft:golden_axe",
"minecraft:diamond_axe",
"minecraft:netherite_axe"
"minecraft:netherite_axe",
"#minecraft:axes"
]
}
@@ -5,6 +5,7 @@
"minecraft:iron_hoe",
"minecraft:golden_hoe",
"minecraft:diamond_hoe",
"minecraft:netherite_hoe"
"minecraft:netherite_hoe",
"#minecraft:hoes"
]
}
@@ -5,6 +5,7 @@
"minecraft:iron_pickaxe",
"minecraft:golden_pickaxe",
"minecraft:diamond_pickaxe",
"minecraft:netherite_pickaxe"
"minecraft:netherite_pickaxe",
"#minecraft:pickaxes"
]
}
@@ -5,6 +5,7 @@
"minecraft:iron_shovel",
"minecraft:golden_shovel",
"minecraft:diamond_shovel",
"minecraft:netherite_shovel"
"minecraft:netherite_shovel",
"#minecraft:shovels"
]
}
@@ -5,6 +5,7 @@
"minecraft:iron_sword",
"minecraft:golden_sword",
"minecraft:diamond_sword",
"minecraft:netherite_sword"
"minecraft:netherite_sword",
"#minecraft:swords"
]
}
@@ -17,5 +17,6 @@
"result": {
"count": 3,
"item": "minecraft:acacia_fence"
}
},
"show_notification": true
}
@@ -16,5 +16,6 @@
],
"result": {
"item": "minecraft:acacia_fence_gate"
}
},
"show_notification": true
}
@@ -18,5 +18,6 @@
"result": {
"count": 3,
"item": "minecraft:acacia_sign"
}
},
"show_notification": true
}
@@ -20,5 +20,6 @@
"result": {
"count": 6,
"item": "minecraft:activator_rail"
}
},
"show_notification": true
}
@@ -16,5 +16,6 @@
],
"result": {
"item": "minecraft:anvil"
}
},
"show_notification": true
}
@@ -16,5 +16,6 @@
],
"result": {
"item": "minecraft:armor_stand"
}
},
"show_notification": true
}
Loaded 100 of 337 files, more files were not shown because too many files have changed in this diff. Show more