From 6bd60d42339482580dd7f501d5ff436f63945a97 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 24 Dec 2024 01:43:04 +0800 Subject: [PATCH] Fix: Default components breaking item stacking while crafting. --- .../geysermc/geyser/entity/type/ItemFrameEntity.java | 12 +----------- .../java/org/geysermc/geyser/item/type/Item.java | 11 +++++++++-- .../translator/inventory/InventoryTranslator.java | 2 +- .../geyser/translator/item/BedrockItemBuilder.java | 5 +++-- .../geyser/translator/item/ItemTranslator.java | 2 +- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java index acb3df2b6..ba3dfb79d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java @@ -118,17 +118,7 @@ public class ItemFrameEntity extends Entity { NbtMapBuilder builder = NbtMap.builder(); builder.putByte("Count", (byte) itemData.getCount()); NbtMap itemDataTag = itemData.getTag(); - if (itemDataTag != null) { - // Remove custom name that Geyser sets for items due to translating default components - String customName = ItemTranslator.getCustomName(session, heldItem.getDataComponents(), - session.getItemMappings().getMapping(heldItem), 'f', false); - if (customName == null) { - // No custom name found, must modify tag if custom name exists - NbtMapBuilder copy = itemDataTag.toBuilder(); - copy.remove("display"); // Also removes lore, but, should not matter - itemDataTag = copy.build(); - } - + if (itemData.getTag() != null) { builder.put("tag", itemDataTag); } builder.putShort("Damage", (short) itemData.getDamage()); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java index 19789e086..738d57788 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java @@ -191,7 +191,9 @@ public class Item { } Integer repairCost = components.get(DataComponentType.REPAIR_COST); - if (repairCost != null) { + // Java sets repair cost to 0 on all items via default components, that trips up Bedrock crafting. + // See https://github.com/GeyserMC/Geyser/issues/5220 for more details + if (repairCost != null && repairCost != 0) { builder.putInt("RepairCost", repairCost); } @@ -202,7 +204,12 @@ public class Item { // Prevents the client from trying to stack items with untranslated components // Relies on correct hash code implementation, and some luck - builder.putInt("GeyserHash", components.hashCode()); // TODO: don't rely on this + // However, we should only set a hash when the components differ from the default ones, + // otherwise Bedrock can't stack these when crafting items since it's predicted recipe output + // does not contain the GeyserHash. See https://github.com/GeyserMC/Geyser/issues/5220 for more details + if (!baseComponents.equals(components)) { + builder.putInt("GeyserHash", components.hashCode()); // TODO: don't rely on this + } } /** diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index f7e3bfc2a..b4f507af5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -246,7 +246,7 @@ public abstract class InventoryTranslator { boolean isSourceCursor = isCursor(transferAction.getSource()); boolean isDestCursor = isCursor(transferAction.getDestination()); - if ((this) instanceof PlayerInventoryTranslator) { + if (this instanceof PlayerInventoryTranslator) { if (destSlot == 5) { //only set the head if the destination is the head slot GeyserItemStack javaItem = inventory.getItem(sourceSlot); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java index e989288c2..2f51c0007 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/BedrockItemBuilder.java @@ -122,12 +122,13 @@ public final class BedrockItemBuilder { */ @Nullable public NbtMap build() { - if (customName != null || lore != null) { + boolean validLore = lore != null && !lore.isEmpty(); + if (customName != null || validLore) { NbtMapBuilder display = NbtMap.builder(); if (customName != null) { display.putString("Name", customName); } - if (lore != null) { + if (validLore) { display.putList("Lore", NbtType.STRING, lore); } getOrCreateNbt().put("display", display.build()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java index 96b64f56d..b8959c7b8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java @@ -173,7 +173,7 @@ public final class ItemTranslator { javaItem.translateComponentsToBedrock(session, components, nbtBuilder); Rarity rarity = Rarity.fromId(components.getOrDefault(DataComponentType.RARITY, 0)); - String customName = getCustomName(session, components, bedrockItem, rarity.getColor(), true); + String customName = getCustomName(session, components, bedrockItem, rarity.getColor(), false); if (customName != null) { nbtBuilder.setCustomName(customName); }