fix: Item.equal now compares components on 1.20.5+ - #183
Open
AnonymoDGH wants to merge 1 commit into
Open
Conversation
Since 1.20.5 item data (custom name, damage, enchantments, lore, ...) is stored in components instead of NBT, but Item.equal only compared type/metadata/count/nbt. Two items differing only in components were therefore reported as equal, which breaks item synchronization in mineflayer (PrismarineJS/mineflayer#3933): inventory.js gates updateSlot on Item.equal, so component changes were silently dropped. Add a componentsEqual helper that compares componentMap entries and removedComponents, evaluated under the existing matchNbt flag (components are the 1.20.5+ replacement for NBT item data). Pre-1.20.5 items have no componentMap and are unaffected. Adds regression tests for all cases.
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
Since 1.20.5, item data (custom name, damage, enchantments, lore, repair cost, ...) is stored in
components/componentMapinstead of NBT. ButItem.equalonly comparestype,metadata,countandnbt— so two items that differ only in their components are reported as equal.Reproduction (1.20.5):
Same for
damage,enchantments, andremovedComponentsdifferences.This is the root cause behind PrismarineJS/mineflayer#3933: mineflayer's
inventory.jsgatesupdateSlotonItem.equal(if (!Item.equal(bot.inventory.slots[slot], item, true)) bot.inventory.updateSlot(slot, item)), so on 1.20.5+ component changes (renames, damage, enchants) are silently dropped and items fail to synchronize.Fix
Add a
componentsEqualhelper that comparescomponentMapentries (by type and serialized data) andremovedComponents, and evaluate it insideItem.equalunder the existingmatchNbtflag — components are the 1.20.5+ replacement for NBT item data, so they belong to the same "match item data" semantics.componentMapand are completely unaffected (helper returns true immediately).matchNbt=falseskips component comparison, consistent with skipping NBT.Verification
custom_name, differentdamage, differentenchantments, identical components, differentremovedComponents, andmatchNbt=false.standardlint clean.