diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 39357eb60..1443a9443 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -152,29 +152,37 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatE import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; public final class EntityDefinitions { + public static final EntityDefinition ACACIA_BOAT; + public static final EntityDefinition ACACIA_CHEST_BOAT; public static final EntityDefinition ALLAY; public static final EntityDefinition AREA_EFFECT_CLOUD; public static final EntityDefinition ARMADILLO; public static final EntityDefinition ARMOR_STAND; public static final EntityDefinition ARROW; public static final EntityDefinition AXOLOTL; + public static final EntityDefinition BAMBOO_RAFT; + public static final EntityDefinition BAMBOO_CHEST_RAFT; public static final EntityDefinition BAT; public static final EntityDefinition BEE; + public static final EntityDefinition BIRCH_BOAT; + public static final EntityDefinition BIRCH_CHEST_BOAT; public static final EntityDefinition BLAZE; - public static final EntityDefinition BOAT; public static final EntityDefinition BOGGED; public static final EntityDefinition BREEZE; public static final EntityDefinition BREEZE_WIND_CHARGE; public static final EntityDefinition CAMEL; public static final EntityDefinition CAT; public static final EntityDefinition CAVE_SPIDER; + public static final EntityDefinition CHERRY_BOAT; + public static final EntityDefinition CHERRY_CHEST_BOAT; public static final EntityDefinition CHEST_MINECART; public static final EntityDefinition CHICKEN; - public static final EntityDefinition CHEST_BOAT; public static final EntityDefinition COD; public static final EntityDefinition COMMAND_BLOCK_MINECART; public static final EntityDefinition COW; public static final EntityDefinition CREEPER; + public static final EntityDefinition DARK_OAK_BOAT; + public static final EntityDefinition DARK_OAK_CHEST_BOAT; public static final EntityDefinition DOLPHIN; public static final EntityDefinition DONKEY; public static final EntityDefinition DRAGON_FIREBALL; @@ -213,14 +221,20 @@ public final class EntityDefinitions { public static final EntityDefinition IRON_GOLEM; public static final EntityDefinition ITEM; public static final EntityDefinition ITEM_FRAME; + public static final EntityDefinition JUNGLE_BOAT; + public static final EntityDefinition JUNGLE_CHEST_BOAT; public static final EntityDefinition LEASH_KNOT; public static final EntityDefinition LIGHTNING_BOLT; public static final EntityDefinition LLAMA; public static final EntityDefinition LLAMA_SPIT; public static final EntityDefinition MAGMA_CUBE; + public static final EntityDefinition MANGROVE_BOAT; + public static final EntityDefinition MANGROVE_CHEST_BOAT; public static final EntityDefinition MINECART; public static final EntityDefinition MOOSHROOM; public static final EntityDefinition MULE; + public static final EntityDefinition OAK_BOAT; + public static final EntityDefinition OAK_CHEST_BOAT; public static final EntityDefinition OCELOT; public static final EntityDefinition PAINTING; public static final EntityDefinition PANDA; @@ -251,6 +265,8 @@ public final class EntityDefinitions { public static final EntityDefinition SPAWNER_MINECART; // Not present on Bedrock public static final EntityDefinition SPECTRAL_ARROW; public static final EntityDefinition SPIDER; + public static final EntityDefinition SPRUCE_BOAT; + public static final EntityDefinition SPRUCE_CHEST_BOAT; public static final EntityDefinition SQUID; public static final EntityDefinition STRAY; public static final EntityDefinition STRIDER; @@ -309,23 +325,6 @@ public final class EntityDefinitions { .addTranslator(null) // Waiting .addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle) .build(); - BOAT = EntityDefinition.inherited(BoatEntity::new, entityBase) - .type(EntityType.BOAT) - .height(0.6f).width(1.6f) - .offset(0.35f) - .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit - .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction - .addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) -> - // 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock - boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue()))) - .addTranslator(MetadataType.INT, BoatEntity::setVariant) - .addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft) - .addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight) - .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything - .build(); - CHEST_BOAT = EntityDefinition.inherited(ChestBoatEntity::new, BOAT) - .type(EntityType.CHEST_BOAT) - .build(); DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase) .type(EntityType.DRAGON_FIREBALL) .heightAndWidth(1.0f) @@ -568,6 +567,45 @@ public final class EntityDefinitions { .build(false); } + // Boats + { + EntityDefinition boatBase = EntityDefinition.inherited(null, entityBase) + .height(0.6f).width(1.6f) + .offset(0.35f) + .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit + .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction + .addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) -> + // 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock + boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue()))) + .addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft) + .addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight) + .addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything + .build(); + + ACACIA_BOAT = buildBoat(boatBase, EntityType.ACACIA_BOAT, BoatEntity.BoatVariant.ACACIA); + BAMBOO_RAFT = buildBoat(boatBase, EntityType.BAMBOO_RAFT, BoatEntity.BoatVariant.BAMBOO); + BIRCH_BOAT = buildBoat(boatBase, EntityType.BIRCH_BOAT, BoatEntity.BoatVariant.BIRCH); + CHERRY_BOAT = buildBoat(boatBase, EntityType.CHERRY_BOAT, BoatEntity.BoatVariant.CHERRY); + DARK_OAK_BOAT = buildBoat(boatBase, EntityType.DARK_OAK_BOAT, BoatEntity.BoatVariant.DARK_OAK); + JUNGLE_BOAT = buildBoat(boatBase, EntityType.JUNGLE_BOAT, BoatEntity.BoatVariant.JUNGLE); + MANGROVE_BOAT = buildBoat(boatBase, EntityType.MANGROVE_BOAT, BoatEntity.BoatVariant.MANGROVE); + OAK_BOAT = buildBoat(boatBase, EntityType.OAK_BOAT, BoatEntity.BoatVariant.OAK); + SPRUCE_BOAT = buildBoat(boatBase, EntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE); + + EntityDefinition chestBoatBase = EntityDefinition.inherited(null, boatBase) + .build(); + + ACACIA_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.ACACIA_CHEST_BOAT, BoatEntity.BoatVariant.ACACIA); + BAMBOO_CHEST_RAFT = buildChestBoat(chestBoatBase, EntityType.BAMBOO_CHEST_RAFT, BoatEntity.BoatVariant.BAMBOO); + BIRCH_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.BIRCH_CHEST_BOAT, BoatEntity.BoatVariant.BIRCH); + CHERRY_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.CHERRY_CHEST_BOAT, BoatEntity.BoatVariant.CHERRY); + DARK_OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.DARK_OAK_CHEST_BOAT, BoatEntity.BoatVariant.DARK_OAK); + JUNGLE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.JUNGLE_CHEST_BOAT, BoatEntity.BoatVariant.JUNGLE); + MANGROVE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.MANGROVE_CHEST_BOAT, BoatEntity.BoatVariant.MANGROVE); + OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.OAK_CHEST_BOAT, BoatEntity.BoatVariant.OAK); + SPRUCE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.SPRUCE_CHEST_BOAT, BoatEntity.BoatVariant.SPRUCE); + } + EntityDefinition livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase) .addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags) .addTranslator(MetadataType.FLOAT, LivingEntity::setHealth) @@ -1128,6 +1166,22 @@ public final class EntityDefinitions { } } + private static EntityDefinition buildBoat(EntityDefinition base, EntityType entityType, BoatEntity.BoatVariant variant) { + return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) -> + new BoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base) + .type(entityType) + .identifier("minecraft:boat") + .build(); + } + + private static EntityDefinition buildChestBoat(EntityDefinition base, EntityType entityType, BoatEntity.BoatVariant variant) { + return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) -> + new ChestBoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base) + .type(entityType) + .identifier("minecraft:chest_boat") + .build(); + } + public static void init() { // no-op } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java index 47ae6777a..9312d83f5 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java @@ -32,11 +32,12 @@ import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; 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.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; @@ -63,16 +64,19 @@ public class BoatEntity extends Entity implements Leashable, Tickable { * Saved for using the "pick" functionality on a boat. */ @Getter - private int variant; + protected final BoatVariant variant; private long leashHolderBedrockId = -1; // Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it private final float ROWING_SPEED = 0.1f; - public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) { // Initial rotation is incorrect super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90); + this.variant = variant; + + dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal()); // Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+ dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true); @@ -124,15 +128,6 @@ public class BoatEntity extends Entity implements Leashable, Tickable { moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround); } - public void setVariant(IntEntityMetadata entityMetadata) { - variant = entityMetadata.getPrimitiveValue(); - dirtyMetadata.put(EntityDataTypes.VARIANT, switch (variant) { - case 6, 7, 8 -> variant - 1; // dark_oak, mangrove, bamboo - case 5 -> 8; // cherry - default -> variant; - }); - } - public void setPaddlingLeft(BooleanEntityMetadata entityMetadata) { isPaddlingLeft = entityMetadata.getPrimitiveValue(); if (!isPaddlingLeft) { @@ -212,6 +207,10 @@ public class BoatEntity extends Entity implements Leashable, Tickable { return leashHolderBedrockId; } + public Item getPickItem() { + return variant.pickItem; + } + private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) { AnimatePacket packet = new AnimatePacket(); packet.setRuntimeEntityId(rower.getGeyserId()); @@ -219,4 +218,27 @@ public class BoatEntity extends Entity implements Leashable, Tickable { packet.setRowingTime(rowTime); session.sendUpstreamPacket(packet); } + + /** + * Ordered by Bedrock ordinal + */ + public enum BoatVariant { + OAK(Items.OAK_BOAT, Items.OAK_CHEST_BOAT), + SPRUCE(Items.SPRUCE_BOAT, Items.SPRUCE_CHEST_BOAT), + BIRCH(Items.BIRCH_BOAT, Items.BIRCH_CHEST_BOAT), + JUNGLE(Items.JUNGLE_BOAT, Items.JUNGLE_CHEST_BOAT), + ACACIA(Items.ACACIA_BOAT, Items.ACACIA_CHEST_BOAT), + DARK_OAK(Items.DARK_OAK_BOAT, Items.DARK_OAK_CHEST_BOAT), + MANGROVE(Items.MANGROVE_BOAT, Items.MANGROVE_CHEST_BOAT), + BAMBOO(Items.BAMBOO_RAFT, Items.BAMBOO_CHEST_RAFT), + CHERRY(Items.CHERRY_BOAT, Items.CHERRY_CHEST_BOAT); + + private final Item pickItem; + final Item chestPickItem; + + BoatVariant(Item pickItem, Item chestPickItem) { + this.pickItem = pickItem; + this.chestPickItem = chestPickItem; + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java index 479b4d80d..967da41df 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ChestBoatEntity.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type; import org.cloudburstmc.math.vector.Vector3f; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; @@ -35,8 +36,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; public class ChestBoatEntity extends BoatEntity { - public ChestBoatEntity(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); + public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) { + super(session, entityId, geyserId, uuid, definition, position, motion, yaw, variant); } @Override @@ -48,4 +49,9 @@ public class ChestBoatEntity extends BoatEntity { public InteractionResult interact(Hand hand) { return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS; } + + @Override + public Item getPickItem() { + return this.variant.chestPickItem; + } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java index e85456c33..acb8573fb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockEntityPickRequestTranslator.java @@ -51,29 +51,14 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator { - // Include type of boat in the name - int variant = ((BoatEntity) entity).getVariant(); - String typeOfBoat = switch (variant) { - case 1 -> "spruce"; - case 2 -> "birch"; - case 3 -> "jungle"; - case 4 -> "acacia"; - case 5 -> "cherry"; - case 6 -> "dark_oak"; - case 7 -> "mangrove"; - case 8 -> "bamboo"; - default -> "oak"; - }; - itemName = typeOfBoat + "_" + entity.getDefinition().entityType().name().toLowerCase(Locale.ROOT); - // Bamboo boat is a raft - if (variant == 8) { - itemName = itemName.replace("boat", "raft"); - } - } case LEASH_KNOT -> itemName = "lead"; case CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART, HOPPER_MINECART, TNT_MINECART -> // The Bedrock identifier matches the item name which moves MINECART to the end of the name diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index 6ae21067f..7ed4ac72c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -296,6 +296,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator case OPEN_INVENTORY: if (session.getOpenInventory() == null) { Entity ridingEntity = session.getPlayerEntity().getVehicle(); - if (ridingEntity instanceof AbstractHorseEntity || (ridingEntity != null && ridingEntity.getDefinition().entityType() == EntityType.CHEST_BOAT)) { + if (ridingEntity instanceof AbstractHorseEntity || ridingEntity instanceof ChestBoatEntity) { // This mob has an inventory of its own that we should open instead. ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY); session.sendDownstreamGamePacket(openVehicleWindowPacket); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java index ee80cac16..c4cb10127 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java @@ -84,7 +84,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator mountedHeightOffset = height * 0.6f; case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART, COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0; - case BOAT, CHEST_BOAT -> { - boolean isBamboo = ((BoatEntity) mount).getVariant() == 8; - mountedHeightOffset = isBamboo ? 0.25f : -0.1f; - } + case BAMBOO_RAFT, BAMBOO_CHEST_RAFT -> mountedHeightOffset = 0.25f; case HOGLIN, ZOGLIN -> { boolean isBaby = mount.getFlag(EntityFlag.BABY); mountedHeightOffset = height - (isBaby ? 0.2f : 0.15f); @@ -174,15 +177,6 @@ public final class EntityUtils { float yOffset = mountedHeightOffset + heightOffset; float zOffset = 0; switch (mount.getDefinition().entityType()) { - case BOAT -> { - // Without the X offset, more than one entity on a boat is stacked on top of each other - if (moreThanOneEntity) { - xOffset = rider ? 0.2f : -0.6f; - if (passenger instanceof AnimalEntity) { - xOffset += 0.2f; - } - } - } case CAMEL -> { zOffset = 0.5f; if (moreThanOneEntity) { @@ -201,7 +195,6 @@ public final class EntityUtils { } } } - case CHEST_BOAT -> xOffset = 0.15F; case CHICKEN -> zOffset = -0.1f; case TRADER_LLAMA, LLAMA -> zOffset = -0.3f; case TEXT_DISPLAY -> { @@ -217,6 +210,17 @@ public final class EntityUtils { } } } + if (mount instanceof ChestBoatEntity) { + xOffset = 0.15F; + } else if (mount instanceof BoatEntity) { + // Without the X offset, more than one entity on a boat is stacked on top of each other + if (moreThanOneEntity) { + xOffset = rider ? 0.2f : -0.6f; + if (passenger instanceof AnimalEntity) { + xOffset += 0.2f; + } + } + } /* * Bedrock Differences * Zoglin & Hoglin seem to be taller in Bedrock edition @@ -231,13 +235,19 @@ public final class EntityUtils { } switch (mount.getDefinition().entityType()) { case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART, - COMMAND_BLOCK_MINECART, BOAT, CHEST_BOAT -> yOffset -= mount.getDefinition().height() * 0.5f; + COMMAND_BLOCK_MINECART -> yOffset -= mount.getDefinition().height() * 0.5f; } switch (passenger.getDefinition().entityType()) { case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART, - COMMAND_BLOCK_MINECART, BOAT, CHEST_BOAT -> yOffset += passenger.getDefinition().height() * 0.5f; + COMMAND_BLOCK_MINECART -> yOffset += passenger.getDefinition().height() * 0.5f; case FALLING_BLOCK -> yOffset += 0.5f; } + if (mount instanceof BoatEntity) { + yOffset -= mount.getDefinition().height() * 0.5f; + } + if (passenger instanceof BoatEntity) { + yOffset += passenger.getDefinition().height() * 0.5f; + } if (mount instanceof ArmorStandEntity armorStand) { yOffset -= armorStand.getYOffset(); } diff --git a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index a0bd5a4c7..11ed17872 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -485,7 +485,7 @@ public class InventoryUtils { } for (int i = 0; i < data.ingredients().length; i++) { Ingredient ingredient = data.ingredients()[i]; - for (ItemStack itemStack : ingredient.getOptions()) { + for (int item : ingredient.getValues().getHolders()) { // FIXME boolean inventoryHasItem = false; // Iterate only over the crafting table to find this item crafting: @@ -493,11 +493,11 @@ public class InventoryUtils { for (int col = firstCol; col < width + firstCol; col++) { GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1); if (geyserItemStack.isEmpty()) { - inventoryHasItem = itemStack == null || itemStack.getId() == 0; + inventoryHasItem = item == 0; if (inventoryHasItem) { break crafting; } - } else if (itemStack.equals(geyserItemStack.getItemStack(1))) { + } else if (item == geyserItemStack.getJavaId()) { inventoryHasItem = true; break crafting; } @@ -522,14 +522,15 @@ public class InventoryUtils { for (int col = firstCol; col < width + firstCol; col++) { GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1); Ingredient ingredient = ingredients[ingredientIndex++]; - if (ingredient.getOptions().length == 0) { + int[] items = ingredient.getValues().getHolders(); // FIXME + if (items.length == 0) { if (!geyserItemStack.isEmpty()) { return false; } } else { boolean inventoryHasItem = false; - for (ItemStack item : ingredient.getOptions()) { - if (Objects.equals(geyserItemStack.getItemStack(1), item)) { + for (int item : items) { + if (geyserItemStack.getJavaId() == item) { inventoryHasItem = true; break; }