Fix NPE in foliaAdapt entity wrapper when getEquipment() is null#26
Open
rugiaDev wants to merge 3 commits into
Open
Fix NPE in foliaAdapt entity wrapper when getEquipment() is null#26rugiaDev wants to merge 3 commits into
rugiaDev wants to merge 3 commits into
Conversation
…unload Paper's CraftLivingEntity.getEquipment() is annotated @NotNull but returns null at runtime for entities without equipment and while a mob is being unloaded. Kotlin inserts a not-null call assertion on the @NotNull return, which throws "getEquipment(...) must not be null" when MythicMobs reads the main-hand item during ActiveMob unload. Add -Xno-call-assertions to the affected NMS modules (v1_21_R6, v1_21_R7, v26_R1) so the genuine null passes through to callers, which already null-check it (e.g. MythicMobs returns Optional.empty()). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…f a compiler flag Replace the previous -Xno-call-assertions workaround with an explicit null check, scoped to the one method that needs it. CraftLivingEntity.getEquipment() is annotated @NotNull but returns null at runtime for entities without equipment and while a mob is being unloaded. The overridden getEquipment() now reads through the @nullable Bukkit LivingEntity interface (so Kotlin inserts no not-null call assertion) and falls back to an empty CraftEntityEquipment when null. This never returns null and never throws, so any caller is safe -- not just ones that null-check. This keeps the module's other Kotlin not-null assertions intact (the compiler flag had disabled them module-wide). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r wrapper Players always have equipment so this never threw, but mirror the entity wrapper's pattern for consistency: read getEquipment() through the @nullable Bukkit LivingEntity interface and fall back to an empty CraftEntityEquipment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Paper (1.21.10+), MythicMobs throws an NPE from the BetterHealthBar
folia-adapt wrapper while a mob is being unloaded:
Cause
In
v1_21_R6/v1_21_R7/v26_R1, thefoliaAdapt(LivingEntity)wrapperoverrides
getEquipment(): EntityEquipment(non-null) and delegates to theunderlying entity. Paper's
CraftLivingEntity.getEquipment()is annotated@NotNull, so Kotlin inserts a not-null call assertion — but the value isactually
nullat runtime for entities without equipment, and for a mob midunload. The assertion then throws.
(
v1_21_R5and earlier declared the override asEntityEquipment?, so theywere never affected — this is a regression introduced when the override return
type became non-null.)
Fix
Read equipment through the
@NullableBukkitLivingEntityinterface (so nonot-null assertion is generated) and fall back to an empty
CraftEntityEquipmentwhen null. This never returns null and never throws, soany caller is safe —
MythicMobs, for example, already null-checks the result.The same null-safe pattern is mirrored on the player wrapper for consistency
(players always have equipment, so it never threw there, but the code is now
uniform).
Affected modules:
v1_21_R6,v1_21_R7,v26_R1.