Skip to content

fix: Item.equal now compares components on 1.20.5+ - #183

Open
AnonymoDGH wants to merge 1 commit into
PrismarineJS:masterfrom
AnonymoDGH:fix/item-equal-components-1.20.5
Open

fix: Item.equal now compares components on 1.20.5+#183
AnonymoDGH wants to merge 1 commit into
PrismarineJS:masterfrom
AnonymoDGH:fix/item-equal-components-1.20.5

Conversation

@AnonymoDGH

Copy link
Copy Markdown

Problem

Since 1.20.5, item data (custom name, damage, enchantments, lore, repair cost, ...) is stored in components/componentMap instead of NBT. But Item.equal only compares type, metadata, count and nbt — so two items that differ only in their components are reported as equal.

Reproduction (1.20.5):

const a = Item.fromNotch({ itemId: swordId, itemCount: 1, components: [{ type: 'custom_name', data: 'Excalibur' }] })
const b = Item.fromNotch({ itemId: swordId, itemCount: 1, components: [] })
Item.equal(a, b) // true  <- wrong, should be false

Same for damage, enchantments, and removedComponents differences.

This is the root cause behind PrismarineJS/mineflayer#3933: mineflayer's inventory.js gates updateSlot on Item.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 componentsEqual helper that compares componentMap entries (by type and serialized data) and removedComponents, and evaluate it inside Item.equal under the existing matchNbt flag — components are the 1.20.5+ replacement for NBT item data, so they belong to the same "match item data" semantics.

  • Pre-1.20.5 items have no componentMap and are completely unaffected (helper returns true immediately).
  • matchNbt=false skips component comparison, consistent with skipping NBT.
  • No signature change; fully backward compatible.

Verification

  • New regression tests cover: different custom_name, different damage, different enchantments, identical components, different removedComponents, and matchNbt=false.
  • Full suite: 114 passing (108 existing + 6 new), standard lint clean.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant