From 8f98162c69c10a58879b1edbd2877ede588cdc7c Mon Sep 17 00:00:00 2001 From: David Choo Date: Wed, 21 Jul 2021 21:48:59 -0400 Subject: [PATCH] Fix Item drop animation (#2406) --- .../geysermc/connector/entity/ItemEntity.java | 78 +++++++++++++++---- .../entity/JavaEntityVelocityTranslator.java | 7 ++ .../world/block/BlockStateValues.java | 22 ++++++ 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index 1615ac8d8..3dcfb0d93 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -28,31 +28,23 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; -public class ItemEntity extends Entity { +public class ItemEntity extends ThrowableEntity { protected ItemData item; + private int waterLevel = -1; + public ItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { - super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation); - } - - @Override - public void setMotion(Vector3f motion) { - if (isOnGround()) - motion = Vector3f.from(motion.getX(), 0, motion.getZ()); - - super.setMotion(motion); - } - - @Override - public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { - super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), rotation, isOnGround, teleported); + super(entityId, geyserId, entityType, position, motion, rotation); } @Override @@ -63,14 +55,63 @@ public class ItemEntity extends Entity { valid = true; AddItemEntityPacket itemPacket = new AddItemEntityPacket(); itemPacket.setRuntimeEntityId(geyserId); + itemPacket.setUniqueEntityId(geyserId); itemPacket.setPosition(position.add(0d, this.entityType.getOffset(), 0d)); itemPacket.setMotion(motion); - itemPacket.setUniqueEntityId(geyserId); itemPacket.setFromFishing(false); itemPacket.setItemInHand(item); + itemPacket.getMetadata().putAll(metadata); session.sendUpstreamPacket(itemPacket); } + @Override + public void tick(GeyserSession session) { + if (isInWater(session)) { + return; + } + if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) { + float gravity = getGravity(session); + motion = motion.down(gravity); + moveAbsoluteImmediate(session, position.add(motion), rotation, onGround, false); + float drag = getDrag(session); + motion = motion.mul(drag, 0.98f, drag); + } + } + + @Override + protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { + float offset = entityType.getOffset(); + if (waterLevel == 0) { // Item is in a full block of water + // Move the item entity down so it doesn't float above the water + offset = -entityType.getOffset(); + } + super.moveAbsoluteImmediate(session, position.add(0, offset, 0), Vector3f.ZERO, isOnGround, teleported); + this.position = position; + + int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt()); + waterLevel = BlockStateValues.getWaterLevel(block); + } + + @Override + protected float getGravity(GeyserSession session) { + if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater(session)) { + // Gravity can change if the item is in water/lava, but + // the server calculates the motion & position for us + return 0.04f; + } + return 0; + } + + @Override + protected float getDrag(GeyserSession session) { + if (onGround) { + Vector3i groundBlockPos = position.toInt().down(1); + int blockState = session.getConnector().getWorldManager().getBlockAt(session, groundBlockPos); + return BlockStateValues.getSlipperiness(blockState) * 0.98f; + } + return 0.98f; + } + @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 8) { @@ -81,4 +122,9 @@ public class ItemEntity extends Entity { super.updateBedrockMetadata(entityMetadata, session); } + + @Override + protected boolean isInWater(GeyserSession session) { + return waterLevel != -1; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java index 1c628503a..3f0b69cdb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.java.entity; import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.ItemEntity; import org.geysermc.connector.entity.living.animal.horse.AbstractHorseEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -54,6 +55,12 @@ public class JavaEntityVelocityTranslator extends PacketTranslator