diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java index 23a7bcc4b..66d3e3880 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java @@ -26,19 +26,16 @@ package org.geysermc.connector.network.translators.java.entity; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntitySetPassengersPacket; -import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.entity.EntityData; -import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData; import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import org.geysermc.connector.entity.Entity; -import org.geysermc.connector.entity.living.ArmorStandEntity; -import org.geysermc.connector.entity.living.animal.AnimalEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.utils.EntityUtils; import java.util.Arrays; @@ -117,9 +114,9 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator 1)); + EntityUtils.updateMountOffset(passenger, entity, session, false, false, (packet.getPassengerIds().length > 1)); } else { - this.updateOffset(passenger, entity, session, (packet.getPassengerIds()[0] == passengerId), true, (packet.getPassengerIds().length > 1)); + EntityUtils.updateMountOffset(passenger, entity, session, (packet.getPassengerIds()[0] == passengerId), true, (packet.getPassengerIds().length > 1)); } // Force an update to the passenger metadata @@ -137,144 +134,4 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator 1); + } + // If coordinates are relative, then add to the existing coordinate double newX = packet.getX() + (packet.getRelative().contains(PositionElement.X) ? entity.getPosition().getX() : 0); diff --git a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java index eb712b135..b5b0d24ca 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java @@ -26,9 +26,16 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.Effect; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.living.ArmorStandEntity; +import org.geysermc.connector.entity.living.animal.AnimalEntity; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; -public class EntityUtils { +public final class EntityUtils { /** * Convert Java edition effect IDs to Bedrock edition @@ -72,4 +79,147 @@ public class EntityUtils { return null; } } + + private static float getMountedHeightOffset(Entity mount) { + float height = mount.getMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT); + float mountedHeightOffset = height * 0.75f; + switch (mount.getEntityType()) { + case CHICKEN: + case SPIDER: + mountedHeightOffset = height * 0.5f; + break; + case DONKEY: + case MULE: + mountedHeightOffset -= 0.25f; + break; + case LLAMA: + mountedHeightOffset = height * 0.67f; + break; + case MINECART: + case MINECART_HOPPER: + case MINECART_TNT: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_SPAWNER: + case MINECART_COMMAND_BLOCK: + mountedHeightOffset = 0; + break; + case BOAT: + mountedHeightOffset = -0.1f; + break; + case HOGLIN: + case ZOGLIN: + boolean isBaby = mount.getMetadata().getFlags().getFlag(EntityFlag.BABY); + mountedHeightOffset = height - (isBaby ? 0.2f : 0.15f); + break; + case PIGLIN: + mountedHeightOffset = height * 0.92f; + break; + case RAVAGER: + mountedHeightOffset = 2.1f; + break; + case SKELETON_HORSE: + mountedHeightOffset -= 0.1875f; + break; + case STRIDER: + mountedHeightOffset = height - 0.19f; + break; + } + return mountedHeightOffset; + } + + private static float getHeightOffset(Entity passenger) { + boolean isBaby; + switch (passenger.getEntityType()) { + case SKELETON: + case STRAY: + case WITHER_SKELETON: + return -0.6f; + case ARMOR_STAND: + if (((ArmorStandEntity) passenger).isMarker()) { + return 0.0f; + } else { + return 0.1f; + } + case ENDERMITE: + case SILVERFISH: + return 0.1f; + case PIGLIN: + case PIGLIN_BRUTE: + case ZOMBIFIED_PIGLIN: + isBaby = passenger.getMetadata().getFlags().getFlag(EntityFlag.BABY); + return isBaby ? -0.05f : -0.45f; + case ZOMBIE: + isBaby = passenger.getMetadata().getFlags().getFlag(EntityFlag.BABY); + return isBaby ? 0.0f : -0.45f; + case EVOKER: + case ILLUSIONER: + case PILLAGER: + case RAVAGER: + case VINDICATOR: + case WITCH: + return -0.45f; + case PLAYER: + return -0.35f; + } + if (passenger instanceof AnimalEntity) { + return 0.14f; + } + return 0f; + } + + /** + * Adjust an entity's height if they have mounted/dismounted an entity. + */ + public static void updateMountOffset(Entity passenger, Entity mount, GeyserSession session, boolean rider, boolean riding, boolean moreThanOneEntity) { + passenger.getMetadata().getFlags().setFlag(EntityFlag.RIDING, riding); + if (riding) { + // Without the Y offset, Bedrock players will find themselves in the floor when mounting + float mountedHeightOffset = getMountedHeightOffset(mount); + float heightOffset = getHeightOffset(passenger); + + float xOffset = 0; + float yOffset = mountedHeightOffset + heightOffset; + float zOffset = 0; + switch (mount.getEntityType()) { + case BOAT: + // Without the X offset, more than one entity on a boat is stacked on top of each other + if (rider && moreThanOneEntity) { + xOffset = 0.2f; + } else if (moreThanOneEntity) { + xOffset = -0.6f; + } + break; + case CHICKEN: + zOffset = -0.1f; + break; + case LLAMA: + zOffset = -0.3f; + break; + } + /* + * Bedrock Differences + * Zoglin & Hoglin seem to be taller in Bedrock edition + * Horses are tinier + * Players, Minecarts, and Boats have different origins + */ + if (passenger.getEntityType() == EntityType.PLAYER && mount.getEntityType() != EntityType.PLAYER) { + yOffset += EntityType.PLAYER.getOffset(); + } + switch (mount.getEntityType()) { + case MINECART: + case MINECART_HOPPER: + case MINECART_TNT: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_SPAWNER: + case MINECART_COMMAND_BLOCK: + case BOAT: + yOffset -= mount.getEntityType().getHeight() * 0.5f; + } + Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset); + passenger.getMetadata().put(EntityData.RIDER_SEAT_POSITION, offset); + } + passenger.updateBedrockMetadata(session); + } }