diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index c3812057b..d1879becf 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -35,7 +35,6 @@ import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; @@ -46,9 +45,10 @@ import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.HappyGhastVehicleComponent; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.scoreboard.Team; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.EntityUtils; @@ -82,15 +82,6 @@ import java.util.UUID; public class LivingEntity extends Entity { protected EnumMap equipment = new EnumMap<>(EquipmentSlot.class); - protected ItemData helmet = ItemData.AIR; - protected ItemData chestplate = ItemData.AIR; - protected ItemData leggings = ItemData.AIR; - protected ItemData boots = ItemData.AIR; - protected ItemData body = ItemData.AIR; - protected ItemData saddle = ItemData.AIR; - protected ItemData hand = ItemData.AIR; - protected ItemData offhand = ItemData.AIR; - @Getter(value = AccessLevel.NONE) protected float health = 1f; // The default value in Java Edition before any entity metadata is sent @Getter(value = AccessLevel.NONE) @@ -116,40 +107,50 @@ public class LivingEntity extends Entity { public LivingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } - for (EquipmentSlot slot : EquipmentSlot.values()) { - equipment.put(slot, GeyserItemStack.EMPTY); + public GeyserItemStack getItemInSlot(EquipmentSlot slot) { + GeyserItemStack stack = equipment.get(slot); + if (stack == null) { + return GeyserItemStack.EMPTY; } + return stack; + } + + public GeyserItemStack getMainHandItem() { + return getItemInSlot(EquipmentSlot.MAIN_HAND); + } + + public GeyserItemStack getOffHandItem() { + return getItemInSlot(EquipmentSlot.OFF_HAND); + } + + public boolean isHolding(Item item) { + return getMainHandItem().is(item) || getOffHandItem().is(item); } public void setHelmet(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.HELMET, stack); - this.helmet = ItemTranslator.translateToBedrock(session, stack); } public void setChestplate(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.CHESTPLATE, stack); - this.chestplate = ItemTranslator.translateToBedrock(session, stack); } public void setLeggings(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.LEGGINGS, stack); - this.leggings = ItemTranslator.translateToBedrock(session, stack); } public void setBoots(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.BOOTS, stack); - this.boots = ItemTranslator.translateToBedrock(session, stack); } public void setBody(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.BODY, stack); - this.body = ItemTranslator.translateToBedrock(session, stack); } public void setSaddle(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.SADDLE, stack); - this.saddle = ItemTranslator.translateToBedrock(session, stack); boolean saddled = false; if (!stack.isEmpty()) { @@ -162,12 +163,10 @@ public class LivingEntity extends Entity { public void setHand(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.MAIN_HAND, stack); - this.hand = ItemTranslator.translateToBedrock(session, stack); } public void setOffhand(GeyserItemStack stack) { this.equipment.put(EquipmentSlot.OFF_HAND, stack); - this.offhand = ItemTranslator.translateToBedrock(session, stack); } protected void updateSaddled(boolean saddled) { @@ -182,13 +181,9 @@ public class LivingEntity extends Entity { } public void switchHands() { - GeyserItemStack javaOffhand = this.equipment.get(EquipmentSlot.OFF_HAND); + GeyserItemStack offhand = this.equipment.get(EquipmentSlot.OFF_HAND); this.equipment.put(EquipmentSlot.OFF_HAND, this.equipment.get(EquipmentSlot.MAIN_HAND)); - this.equipment.put(EquipmentSlot.MAIN_HAND, javaOffhand); - - ItemData bedrockOffhand = this.offhand; - this.offhand = this.hand; - this.hand = bedrockOffhand; + this.equipment.put(EquipmentSlot.MAIN_HAND, offhand); } @Override @@ -283,11 +278,10 @@ public class LivingEntity extends Entity { } protected boolean hasShield(boolean offhand) { - ItemMapping shieldMapping = session.getItemMappings().getStoredItems().shield(); if (offhand) { - return this.offhand.getDefinition().equals(shieldMapping.getBedrockDefinition()); + return getOffHandItem().is(Items.SHIELD); } else { - return hand.getDefinition().equals(shieldMapping.getBedrockDefinition()); + return getMainHandItem().is(Items.SHIELD); } } @@ -398,39 +392,38 @@ public class LivingEntity extends Entity { return InteractionResult.PASS; } - public void updateArmor(GeyserSession session) { + public void updateArmor() { if (!valid) return; - ItemData helmet = this.helmet; - ItemData chestplate = this.chestplate; + GeyserItemStack helmet = getItemInSlot(EquipmentSlot.HELMET); + GeyserItemStack chestplate = getItemInSlot(EquipmentSlot.CHESTPLATE); // If an entity has a banner on them, it will be in the helmet slot in Java but the chestplate spot in Bedrock // But don't overwrite the chestplate if it isn't empty - ItemMapping banner = session.getItemMappings().getStoredItems().banner(); - if (ItemData.AIR.equals(chestplate) && helmet.getDefinition().equals(banner.getBedrockDefinition())) { - chestplate = this.helmet; - helmet = ItemData.AIR; - } else if (chestplate.getDefinition().equals(banner.getBedrockDefinition())) { + if (chestplate.isEmpty() && helmet.is(session, ItemTag.BANNERS)) { + chestplate = helmet; + helmet = GeyserItemStack.EMPTY; + } else if (chestplate.is(session, ItemTag.BANNERS)) { // Prevent chestplate banners from showing erroneously - chestplate = ItemData.AIR; + chestplate = GeyserItemStack.EMPTY; } MobArmorEquipmentPacket armorEquipmentPacket = new MobArmorEquipmentPacket(); armorEquipmentPacket.setRuntimeEntityId(geyserId); - armorEquipmentPacket.setHelmet(helmet); - armorEquipmentPacket.setChestplate(chestplate); - armorEquipmentPacket.setLeggings(leggings); - armorEquipmentPacket.setBoots(boots); - armorEquipmentPacket.setBody(body); + armorEquipmentPacket.setHelmet(ItemTranslator.translateToBedrock(session, helmet)); + armorEquipmentPacket.setChestplate(ItemTranslator.translateToBedrock(session, chestplate)); + armorEquipmentPacket.setLeggings(ItemTranslator.translateToBedrock(session, getItemInSlot(EquipmentSlot.LEGGINGS))); + armorEquipmentPacket.setBoots(ItemTranslator.translateToBedrock(session, getItemInSlot(EquipmentSlot.BOOTS))); + armorEquipmentPacket.setBody(ItemTranslator.translateToBedrock(session, getItemInSlot(EquipmentSlot.BODY))); session.sendUpstreamPacket(armorEquipmentPacket); } - public void updateMainHand(GeyserSession session) { + public void updateMainHand() { if (!valid) return; MobEquipmentPacket handPacket = new MobEquipmentPacket(); handPacket.setRuntimeEntityId(geyserId); - handPacket.setItem(hand); + handPacket.setItem(ItemTranslator.translateToBedrock(session, getMainHandItem())); handPacket.setHotbarSlot(-1); handPacket.setInventorySlot(0); handPacket.setContainerId(ContainerId.INVENTORY); @@ -438,12 +431,12 @@ public class LivingEntity extends Entity { session.sendUpstreamPacket(handPacket); } - public void updateOffHand(GeyserSession session) { + public void updateOffHand() { if (!valid) return; MobEquipmentPacket offHandPacket = new MobEquipmentPacket(); offHandPacket.setRuntimeEntityId(geyserId); - offHandPacket.setItem(offhand); + offHandPacket.setItem(ItemTranslator.translateToBedrock(session, getOffHandItem())); offHandPacket.setHotbarSlot(-1); offHandPacket.setInventorySlot(0); offHandPacket.setContainerId(ContainerId.OFFHAND); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java index 01a42e527..7df8d7674 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AllayEntity.java @@ -60,9 +60,9 @@ public class AllayEntity extends MobEntity { if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) { // Maybe better as another tag? return InteractiveTag.GIVE_ITEM_TO_ALLAY; - } else if (!this.hand.isValid() && !itemInHand.isEmpty()) { + } else if (getMainHandItem().isEmpty() && !itemInHand.isEmpty()) { return InteractiveTag.GIVE_ITEM_TO_ALLAY; - } else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) { + } else if (!getMainHandItem().isEmpty() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) { // Seems like there isn't a good tag for this yet return InteractiveTag.GIVE_ITEM_TO_ALLAY; } else { @@ -76,10 +76,10 @@ public class AllayEntity extends MobEntity { if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) { //TOCHECK sound return InteractionResult.SUCCESS; - } else if (!this.hand.isValid() && !itemInHand.isEmpty()) { + } else if (getMainHandItem().isEmpty() && !itemInHand.isEmpty()) { //TODO play sound? return InteractionResult.SUCCESS; - } else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) { + } else if (!getMainHandItem().isEmpty() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) { //TOCHECK also play sound here? return InteractionResult.SUCCESS; } else { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java index afbdcca31..e7c9ef843 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java @@ -32,7 +32,6 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.LivingEntity; @@ -42,6 +41,7 @@ import org.geysermc.geyser.scoreboard.Team; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -332,8 +332,7 @@ public class ArmorStandEntity extends LivingEntity { return; } boolean isNametagEmpty = nametag.isEmpty(); - if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR) - || !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offhand.equals(ItemData.AIR))) { + if (!isNametagEmpty && hasAnyEquipment()) { // Reset scale of the proper armor stand setScale(getScale()); // Set the proper armor stand to invisible to show armor @@ -396,6 +395,12 @@ public class ArmorStandEntity extends LivingEntity { } } + private boolean hasAnyEquipment() { + return (!getItemInSlot(EquipmentSlot.HELMET).isEmpty() || !getItemInSlot(EquipmentSlot.CHESTPLATE).isEmpty() + || !getItemInSlot(EquipmentSlot.LEGGINGS).isEmpty() || !getItemInSlot(EquipmentSlot.BOOTS).isEmpty() + || !getMainHandItem().isEmpty() || !getOffHandItem().isEmpty()); + } + @Override public float getBoundingBoxWidth() { // For consistency with getBoundingBoxHeight() diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java index 022e58bc0..358643b0e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java @@ -64,7 +64,7 @@ public class PandaEntity extends AnimalEntity { packet.setRuntimeEntityId(geyserId); packet.setType(EntityEventType.EATING_ITEM); // As of 1.20.5 - pandas can eat cake - packet.setData(this.hand.getDefinition().getRuntimeId() << 16); + packet.setData(session.getItemMappings().getMapping(getMainHandItem()).getBedrockDefinition().getRuntimeId() << 16); session.sendUpstreamPacket(packet); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index 36a126687..186ecd2dd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Entity; @@ -157,8 +156,7 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic vehicleComponent.tickBoost(); } } else { // getHand() for session player seems to always return air - ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().warpedFungusOnAStick().getBedrockDefinition(); - if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { + if (player.isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { vehicleComponent.tickBoost(); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/PigEntity.java index 7ae672bcc..bb629c3d7 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/farm/PigEntity.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Tickable; @@ -116,8 +115,7 @@ public class PigEntity extends TemperatureVariantAnimal implements Tickable, Cli vehicleComponent.tickBoost(); } } else { // getHand() for session player seems to always return air - ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().carrotOnAStick().getBedrockDefinition(); - if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { + if (player.isHolding(Items.CARROT_ON_A_STICK)) { vehicleComponent.tickBoost(); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java index 46911480e..b80301440 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java @@ -47,6 +47,7 @@ import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.ItemUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; @@ -159,17 +160,16 @@ public class WolfEntity extends TameableEntity implements VariantIntHolder { return super.testMobInteraction(hand, itemInHand); } } - if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.body.isValid() && !getFlag(EntityFlag.BABY)) { + if (itemInHand.asItem() == Items.WOLF_ARMOR && !getItemInSlot(EquipmentSlot.BODY).isEmpty() && !getFlag(EntityFlag.BABY)) { return InteractiveTag.EQUIP_WOLF_ARMOR; } - if (itemInHand.asItem() == Items.SHEARS && this.body.isValid() + if (itemInHand.asItem() == Items.SHEARS && !getItemInSlot(EquipmentSlot.BODY).isEmpty() && (!isCurseOfBinding || session.getGameMode().equals(GameMode.CREATIVE))) { return InteractiveTag.REMOVE_WOLF_ARMOR; } if (getFlag(EntityFlag.SITTING) && session.getTagCache().isItem(repairableItems, itemInHand.asItem()) && - this.body.isValid() && this.body.getTag() != null && - this.body.getTag().getInt("Damage") > 0) { + !getItemInSlot(EquipmentSlot.BODY).isEmpty() && getItemInSlot(EquipmentSlot.BODY).isDamaged()) { return InteractiveTag.REPAIR_WOLF_ARMOR; } // Tamed and owned by player - can sit/stand diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java index d08fff06a..16b5cc01c 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java @@ -26,10 +26,10 @@ package org.geysermc.geyser.entity.type.living.monster; import org.cloudburstmc.math.vector.Vector3f; -import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; @@ -49,8 +49,7 @@ public class AbstractSkeletonEntity extends MonsterEntity { dirtyMetadata.put(EntityDataTypes.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0); if ((xd & 4) == 4) { - ItemDefinition bow = session.getItemMappings().getStoredItems().bow().getBedrockDefinition(); - setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, this.hand.getDefinition() == bow || this.offhand.getDefinition() == bow); + setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, isHolding(Items.BOW)); } else { setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, false); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java index 36c412ba7..d98cbb182 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java @@ -42,6 +42,7 @@ import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; import java.util.UUID; @@ -74,14 +75,14 @@ public class PiglinEntity extends BasePiglinEntity { ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow(); boolean toCrossbow = stack != null && stack.asItem() == crossbow.getJavaItem(); - if (toCrossbow ^ this.hand.getDefinition() == crossbow.getBedrockDefinition()) { // If switching to/from crossbow + if (toCrossbow ^ getMainHandItem().is(Items.CROSSBOW)) { // If switching to/from crossbow dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getDefinition(toCrossbow ? 0 : 1)); dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0); setFlag(EntityFlag.CHARGED, false); setFlag(EntityFlag.USING_ITEM, false); updateBedrockMetadata(); - if (this.hand.isValid()) { + if (!getMainHandItem().isEmpty()) { MobEquipmentPacket mobEquipmentPacket = new MobEquipmentPacket(); mobEquipmentPacket.setRuntimeEntityId(geyserId); mobEquipmentPacket.setContainerId(ContainerId.INVENTORY); @@ -96,11 +97,11 @@ public class PiglinEntity extends BasePiglinEntity { } @Override - public void updateMainHand(GeyserSession session) { - super.updateMainHand(session); + public void updateMainHand() { + super.updateMainHand(); - if (this.hand.getDefinition() == session.getItemMappings().getStoredItems().crossbow().getBedrockDefinition()) { - if (this.hand.getTag() != null && this.hand.getTag().containsKey("chargedItem")) { + if (getMainHandItem().is(Items.CROSSBOW)) { + if (getMainHandItem().getComponent(DataComponentTypes.CHARGED_PROJECTILES) != null) { dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE); setFlag(EntityFlag.CHARGING, false); setFlag(EntityFlag.CHARGED, true); @@ -116,12 +117,12 @@ public class PiglinEntity extends BasePiglinEntity { } @Override - public void updateOffHand(GeyserSession session) { + public void updateOffHand() { // Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates - setFlag(EntityFlag.ADMIRING, session.getTagCache().is(ItemTag.PIGLIN_LOVED, session.getItemMappings().getMapping(this.offhand).getJavaItem())); + setFlag(EntityFlag.ADMIRING, getOffHandItem().is(session, ItemTag.PIGLIN_LOVED)); super.updateBedrockMetadata(); - super.updateOffHand(session); + super.updateOffHand(); } @NonNull diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java index fd7448e29..e73052286 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java @@ -28,11 +28,12 @@ package org.geysermc.geyser.entity.type.living.monster.raid; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes; import java.util.UUID; @@ -49,33 +50,32 @@ public class PillagerEntity extends AbstractIllagerEntity { } @Override - public void updateMainHand(GeyserSession session) { + public void updateMainHand() { updateCrossbow(); - super.updateMainHand(session); + super.updateMainHand(); } @Override - public void updateOffHand(GeyserSession session) { + public void updateOffHand() { updateCrossbow(); - super.updateOffHand(session); + super.updateOffHand(); } /** * Check for a crossbow in either the mainhand or offhand. If one exists, indicate that the pillager should be posing */ protected void updateCrossbow() { - ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow(); - ItemData activeCrossbow = null; - if (this.hand.getDefinition() == crossbow.getBedrockDefinition()) { - activeCrossbow = this.hand; - } else if (this.offhand.getDefinition() == crossbow.getBedrockDefinition()) { - activeCrossbow = this.offhand; + GeyserItemStack activeCrossbow = null; + if (getMainHandItem().is(Items.CROSSBOW)) { + activeCrossbow = getMainHandItem(); + } else if (getOffHandItem().is(Items.CROSSBOW)) { + activeCrossbow = getOffHandItem(); } if (activeCrossbow != null) { - if (activeCrossbow.getTag() != null && activeCrossbow.getTag().containsKey("chargedItem")) { + if (activeCrossbow.getComponent(DataComponentTypes.CHARGED_PROJECTILES) != null) { dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE); setFlag(EntityFlag.CHARGING, false); setFlag(EntityFlag.CHARGED, true); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 7e5a24495..660c9152b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -39,7 +39,6 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; @@ -52,6 +51,7 @@ import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; @@ -135,7 +135,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { addPlayerPacket.setPosition(position.sub(0, definition.offset(), 0)); addPlayerPacket.setRotation(getBedrockRotation()); addPlayerPacket.setMotion(motion); - addPlayerPacket.setHand(hand); + addPlayerPacket.setHand(ItemTranslator.translateToBedrock(session, getMainHandItem())); addPlayerPacket.getAdventureSettings().setCommandPermission(CommandPermission.ANY); addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER); addPlayerPacket.setDeviceId(""); @@ -164,12 +164,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { this.nametag = username; this.equipment.clear(); - this.hand = ItemData.AIR; - this.offhand = ItemData.AIR; - this.boots = ItemData.AIR; - this.leggings = ItemData.AIR; - this.chestplate = ItemData.AIR; - this.helmet = ItemData.AIR; } public void resetMetadata() { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java index 4c8d1d20b..fb36e3462 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java @@ -41,6 +41,7 @@ import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkullSkinManager; +import org.geysermc.geyser.translator.item.ItemTranslator; import java.util.Objects; import java.util.UUID; @@ -86,7 +87,7 @@ public class SkullPlayerEntity extends PlayerEntity { addPlayerPacket.setPosition(position.sub(0, definition.offset(), 0)); addPlayerPacket.setRotation(getBedrockRotation()); addPlayerPacket.setMotion(motion); - addPlayerPacket.setHand(hand); + addPlayerPacket.setHand(ItemTranslator.translateToBedrock(session, getMainHandItem())); addPlayerPacket.getAdventureSettings().setCommandPermission(CommandPermission.ANY); addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER); addPlayerPacket.setDeviceId(""); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index 60af08382..a9fa3603c 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -275,6 +275,10 @@ public class GeyserItemStack { return getComponent(DataComponentTypes.MAX_DAMAGE) != null && getComponent(DataComponentTypes.UNBREAKABLE) == null && getComponent(DataComponentTypes.DAMAGE) != null; } + public boolean isDamaged() { + return isDamageable() && getDamage() > 0; + } + public Item asItem() { if (isEmpty()) { return Items.AIR; diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java index 7e63a5999..b0ffe13b2 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java @@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; @@ -75,11 +76,21 @@ public class ItemMappings implements DefinitionRegistry { Object2ObjectMap customBlockItemDefinitions; + /** + * Gets an {@link ItemMapping} from the given {@link GeyserItemStack}. + * + * @param itemStack the itemstack + * @return an item entry from the given item stack + */ + public ItemMapping getMapping(@NonNull GeyserItemStack itemStack) { + return this.getMapping(itemStack.getJavaId()); + } + /** * Gets an {@link ItemMapping} from the given {@link ItemStack}. * * @param itemStack the itemstack - * @return an item entry from the given java edition identifier + * @return an item entry from the given java edition item stack */ @NonNull public ItemMapping getMapping(@NonNull ItemStack itemStack) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index 7eb62bfb5..82a90bba3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java @@ -259,8 +259,8 @@ public class JavaEntityEventTranslator extends PacketTranslator