diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
index 393517aa2..920e6baf5 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
@@ -29,6 +29,7 @@ import lombok.AllArgsConstructor;
 import net.md_5.bungee.api.ProxyServer;
 import net.md_5.bungee.api.ServerPing;
 import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.TextComponent;
 import net.md_5.bungee.api.config.ListenerInfo;
 import net.md_5.bungee.api.connection.PendingConnection;
 import net.md_5.bungee.api.event.ProxyPingEvent;
@@ -52,8 +53,11 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
     public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
         CompletableFuture<ProxyPingEvent> future = new CompletableFuture<>();
         proxyServer.getPluginManager().callEvent(new ProxyPingEvent(new GeyserPendingConnection(inetSocketAddress), getPingInfo(), (event, throwable) -> {
-            if (throwable != null) future.completeExceptionally(throwable);
-            else future.complete(event);
+            if (throwable != null) {
+                future.completeExceptionally(throwable);
+            } else {
+                future.complete(event);
+            }
         }));
         ProxyPingEvent event = future.join();
         ServerPing response = event.getResponse();
@@ -76,9 +80,12 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
 
     private ServerPing getPingInfo() {
         return new ServerPing(
-                new ServerPing.Protocol(proxyServer.getName() + " " + proxyServer.getGameVersion(), ProtocolConstants.SUPPORTED_VERSION_IDS.get(ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1)),
+                new ServerPing.Protocol(
+                        proxyServer.getName() + " " + ProtocolConstants.SUPPORTED_VERSIONS.get(0) + "-" + ProtocolConstants.SUPPORTED_VERSIONS.get(ProtocolConstants.SUPPORTED_VERSIONS.size() - 1),
+                        ProtocolConstants.SUPPORTED_VERSION_IDS.get(ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1)),
                 new ServerPing.Players(getDefaultListener().getMaxPlayers(), proxyServer.getOnlineCount(), null),
-                getDefaultListener().getMotd(), proxyServer.getConfig().getFaviconObject()
+                TextComponent.fromLegacyText(getDefaultListener().getMotd())[0],
+                proxyServer.getConfig().getFaviconObject()
         );
     }
 
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
index a6ec9e329..2158e7503 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
@@ -57,8 +57,8 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
             Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add);
             return geyserPingInfo;
         } catch (Exception e) {
-            logger.debug("Error while getting Bukkit ping passthrough: " + e.toString());
-            return new GeyserPingInfo(null, null, null);
+            logger.debug("Error while getting Bukkit ping passthrough: " + e);
+            return null;
         }
     }
 
@@ -79,5 +79,4 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
             return Collections.emptyIterator();
         }
     }
-
 }
diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml
index e8653ee8e..293d0cbdc 100644
--- a/bootstrap/standalone/pom.xml
+++ b/bootstrap/standalone/pom.xml
@@ -11,7 +11,7 @@
     <artifactId>bootstrap-standalone</artifactId>
 
     <properties>
-        <log4j.version>2.16.0</log4j.version>
+        <log4j.version>2.17.0</log4j.version>
     </properties>
 
     <dependencies>
diff --git a/core/pom.xml b/core/pom.xml
index de264f908..4da6bdbe0 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -83,7 +83,7 @@
         </dependency>
         <dependency>
             <groupId>com.nukkitx.fastutil</groupId>
-            <artifactId>fastutil-long-long-maps</artifactId>
+            <artifactId>fastutil-int-long-maps</artifactId>
             <version>${fastutil.version}</version>
             <scope>compile</scope>
         </dependency>
@@ -155,7 +155,7 @@
         <dependency>
             <groupId>com.github.GeyserMC</groupId>
             <artifactId>MCProtocolLib</artifactId>
-            <version>c247b1f</version>
+            <version>6a23a780</version>
             <scope>compile</scope>
             <exclusions>
                 <exclusion>
diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
index f66a0c56b..9b8f3aa86 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
@@ -32,7 +32,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.entity.factory.BaseEntityFactory;
 import org.geysermc.geyser.entity.factory.EntityFactory;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.registry.Registries;
@@ -52,10 +51,6 @@ import java.util.function.BiConsumer;
 public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, EntityType entityType, String identifier,
                                                  float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
 
-    public static <T extends Entity> Builder<T> inherited(BaseEntityFactory<T> factory, EntityDefinition<? super T> parent) {
-        return inherited((EntityFactory<T>) factory, parent);
-    }
-
     public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinition<? super T> parent) {
         return new Builder<>(factory, parent.entityType, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators));
     }
@@ -64,7 +59,6 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
         return new Builder<>(factory);
     }
 
-
     public <M> void translateMetadata(T entity, EntityMetadata<M, ? extends MetadataType<M>> metadata) {
         EntityMetadataTranslator<? super T, M, EntityMetadata<M, ? extends MetadataType<M>>> translator = (EntityMetadataTranslator<? super T, M, EntityMetadata<M, ? extends MetadataType<M>>>) this.translators.get(metadata.getId());
         if (translator == null) {
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 e1f2169ef..f35e106d2 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java
@@ -31,9 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEnt
 import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
 import com.nukkitx.protocol.bedrock.data.entity.EntityData;
 import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
-import org.geysermc.geyser.entity.factory.BaseEntityFactory;
-import org.geysermc.geyser.entity.factory.ExperienceOrbEntityFactory;
-import org.geysermc.geyser.entity.factory.PaintingEntityFactory;
 import org.geysermc.geyser.entity.type.*;
 import org.geysermc.geyser.entity.type.living.*;
 import org.geysermc.geyser.entity.type.living.animal.*;
@@ -50,8 +47,8 @@ import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity
 import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity;
 import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity;
 import org.geysermc.geyser.entity.type.player.PlayerEntity;
-import org.geysermc.geyser.translator.text.MessageTranslator;
 import org.geysermc.geyser.registry.Registries;
+import org.geysermc.geyser.translator.text.MessageTranslator;
 
 public final class EntityDefinitions {
     public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
@@ -82,7 +79,7 @@ public final class EntityDefinitions {
     public static final EntityDefinition<ThrowableItemEntity> ENDER_PEARL;
     public static final EntityDefinition<EnderCrystalEntity> END_CRYSTAL;
     public static final EntityDefinition<SpellcasterIllagerEntity> EVOKER;
-    public static final EntityDefinition<Entity> EVOKER_FANGS;
+    public static final EntityDefinition<EvokerFangsEntity> EVOKER_FANGS;
     public static final EntityDefinition<ThrowableItemEntity> EXPERIENCE_BOTTLE;
     public static final EntityDefinition<ExpOrbEntity> EXPERIENCE_ORB;
     public static final EntityDefinition<Entity> EYE_OF_ENDER;
@@ -177,14 +174,14 @@ public final class EntityDefinitions {
     public static final EntityDefinition<WitherSkullEntity> WITHER_SKULL_DANGEROUS;
 
     static {
-        EntityDefinition<Entity> entityBase = EntityDefinition.builder((BaseEntityFactory<Entity>) Entity::new)
+        EntityDefinition<Entity> entityBase = EntityDefinition.builder(Entity::new)
                 .addTranslator(MetadataType.BYTE, Entity::setFlags)
                 .addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
                 .addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
                 .addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
                 .addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.SILENT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
                 .addTranslator(MetadataType.BOOLEAN, Entity::setGravity)
-                .addTranslator(MetadataType.POSE, Entity::setPose)
+                .addTranslator(MetadataType.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
                 .addTranslator(MetadataType.INT, Entity::setFreezing)
                 .build();
 
@@ -224,11 +221,11 @@ public final class EntityDefinitions {
                     .addTranslator(MetadataType.BOOLEAN,
                             (enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal
                     .build();
-            EXPERIENCE_ORB = EntityDefinition.inherited((ExperienceOrbEntityFactory) ExpOrbEntity::new, entityBase)
+            EXPERIENCE_ORB = EntityDefinition.<ExpOrbEntity>inherited(null, entityBase)
                     .type(EntityType.EXPERIENCE_ORB)
                     .identifier("minecraft:xp_orb")
                     .build();
-            EVOKER_FANGS = EntityDefinition.inherited(entityBase.factory(), entityBase)
+            EVOKER_FANGS = EntityDefinition.builder(EvokerFangsEntity::new) // No entity metadata to listen to as of 1.18.1
                     .type(EntityType.EVOKER_FANGS)
                     .height(0.8f).width(0.5f)
                     .identifier("minecraft:evocation_fang")
@@ -275,7 +272,7 @@ public final class EntityDefinitions {
                     .type(EntityType.LLAMA_SPIT)
                     .heightAndWidth(0.25f)
                     .build();
-            PAINTING = EntityDefinition.inherited((PaintingEntityFactory) PaintingEntity::new, entityBase)
+            PAINTING = EntityDefinition.<PaintingEntity>inherited(null, entityBase)
                     .type(EntityType.PAINTING)
                     .build();
             SHULKER_BULLET = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
diff --git a/core/src/main/java/org/geysermc/geyser/entity/factory/BaseEntityFactory.java b/core/src/main/java/org/geysermc/geyser/entity/factory/BaseEntityFactory.java
deleted file mode 100644
index dff1617f9..000000000
--- a/core/src/main/java/org/geysermc/geyser/entity/factory/BaseEntityFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.entity.factory;
-
-import com.nukkitx.math.vector.Vector3f;
-import org.geysermc.geyser.entity.type.Entity;
-import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.session.GeyserSession;
-
-import java.util.UUID;
-
-@FunctionalInterface
-public interface BaseEntityFactory<T extends Entity> extends EntityFactory<T> {
-
-    T create(GeyserSession session, long javaId, long bedrockId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw);
-}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/factory/EntityFactory.java b/core/src/main/java/org/geysermc/geyser/entity/factory/EntityFactory.java
index 774166d44..e541c1f4a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/factory/EntityFactory.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/factory/EntityFactory.java
@@ -25,7 +25,17 @@
 
 package org.geysermc.geyser.entity.factory;
 
+import com.nukkitx.math.vector.Vector3f;
+import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.Entity;
+import org.geysermc.geyser.session.GeyserSession;
 
+import java.util.UUID;
+
+/**
+ * Represents a constructor to create an entity.
+ */
 public interface EntityFactory<T extends Entity> {
+
+    T create(GeyserSession session, int javaId, long bedrockId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw);
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/factory/ExperienceOrbEntityFactory.java b/core/src/main/java/org/geysermc/geyser/entity/factory/ExperienceOrbEntityFactory.java
deleted file mode 100644
index 40a93c08b..000000000
--- a/core/src/main/java/org/geysermc/geyser/entity/factory/ExperienceOrbEntityFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.entity.factory;
-
-import com.nukkitx.math.vector.Vector3f;
-import org.geysermc.geyser.entity.type.ExpOrbEntity;
-import org.geysermc.geyser.session.GeyserSession;
-
-@FunctionalInterface
-public interface ExperienceOrbEntityFactory extends EntityFactory<ExpOrbEntity> {
-
-    ExpOrbEntity create(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position);
-}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/factory/PaintingEntityFactory.java b/core/src/main/java/org/geysermc/geyser/entity/factory/PaintingEntityFactory.java
deleted file mode 100644
index 2990b0ac5..000000000
--- a/core/src/main/java/org/geysermc/geyser/entity/factory/PaintingEntityFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.entity.factory;
-
-import com.nukkitx.math.vector.Vector3f;
-import org.geysermc.geyser.entity.type.PaintingEntity;
-import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.level.PaintingType;
-
-import java.util.UUID;
-
-public interface PaintingEntityFactory extends EntityFactory<PaintingEntity> {
-
-    PaintingEntity create(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction);
-}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java
index b80db2570..35958b4e7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractArrowEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class AbstractArrowEntity extends Entity {
 
-    public AbstractArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractArrowEntity(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);
 
         // Set the correct texture if using the resource pack
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java
index 6063c81f9..3a20bcfdf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/AreaEffectCloudEntity.java
@@ -39,7 +39,7 @@ import java.util.UUID;
 
 public class AreaEffectCloudEntity extends Entity {
 
-    public AreaEffectCloudEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AreaEffectCloudEntity(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);
     }
 
@@ -47,18 +47,19 @@ public class AreaEffectCloudEntity extends Entity {
     protected void initializeMetadata() {
         super.initializeMetadata();
         // Without this the cloud doesn't appear,
-        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600);
+        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, Integer.MAX_VALUE);
 
         // This disabled client side shrink of the cloud
         dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
-        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
-        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
+        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, Float.MIN_VALUE);
+        dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, Float.MIN_VALUE);
 
         setFlag(EntityFlag.FIRE_IMMUNE, true);
     }
 
     public void setRadius(FloatEntityMetadata entityMetadata) {
-        float value = entityMetadata.getPrimitiveValue();
+        // Anything less than 0.5 will cause the cloud to despawn
+        float value = Math.max(entityMetadata.getPrimitiveValue(), 0.5f);
         dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, value);
         dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * value);
     }
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 ac1b3fcbd..16af21eac 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
@@ -65,7 +65,7 @@ public class BoatEntity extends Entity {
     // 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.05f;
 
-    public BoatEntity(GeyserSession session, long 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, float pitch, float headYaw) {
         // Initial rotation is incorrect
         super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
 
@@ -84,8 +84,12 @@ public class BoatEntity extends Entity {
 
         MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
         moveEntityPacket.setRuntimeEntityId(geyserId);
-        // Minimal glitching when ClientboundMoveVehiclePacket is sent
-        moveEntityPacket.setPosition(session.getRidingVehicleEntity() == this ? position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()) : this.position);
+        if (session.getPlayerEntity().getVehicle() == this && session.getPlayerEntity().isRidingInFront()) {
+            // Minimal glitching when ClientboundMoveVehiclePacket is sent
+            moveEntityPacket.setPosition(position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()));
+        } else {
+            moveEntityPacket.setPosition(this.position);
+        }
         moveEntityPacket.setRotation(getBedrockRotation());
         moveEntityPacket.setOnGround(isOnGround);
         moveEntityPacket.setTeleported(teleported);
@@ -128,7 +132,7 @@ public class BoatEntity extends Entity {
             paddleTimeLeft = 0f;
             if (!this.passengers.isEmpty()) {
                 // Get the entity by the first stored passenger and convey motion in this manner
-                Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
+                Entity entity = this.passengers.get(0);
                 if (entity != null) {
                     updateLeftPaddle(session, entity);
                 }
@@ -144,7 +148,7 @@ public class BoatEntity extends Entity {
         if (isPaddlingRight) {
             paddleTimeRight = 0f;
             if (!this.passengers.isEmpty()) {
-                Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
+                Entity entity = this.passengers.get(0);
                 if (entity != null) {
                     updateRightPaddle(session, entity);
                 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java
index 1764c721e..82bec41f6 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
 
-    public CommandBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public CommandBlockMinecartEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java
index ec00c30be..8358d439d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/DefaultBlockMinecartEntity.java
@@ -43,7 +43,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
     public int customBlockOffset = 0;
     public boolean showCustomBlock = false;
 
-    public DefaultBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public DefaultBlockMinecartEntity(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);
 
         dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) 1);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java
index aa907b7c6..5c5cb81ab 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/EnderCrystalEntity.java
@@ -39,7 +39,7 @@ import java.util.UUID;
 
 public class EnderCrystalEntity extends Entity {
 
-    public EnderCrystalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public EnderCrystalEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
index 479ec2e8c..5d26b25b0 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
@@ -39,7 +39,6 @@ import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
 import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
 import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
 import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
-import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.Setter;
@@ -48,8 +47,11 @@ import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.GeyserDirtyMetadata;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.text.MessageTranslator;
+import org.geysermc.geyser.util.EntityUtils;
 import org.geysermc.geyser.util.MathUtils;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
 
@@ -58,7 +60,7 @@ import java.util.UUID;
 public class Entity {
     protected final GeyserSession session;
 
-    protected long entityId;
+    protected int entityId;
     protected final long geyserId;
     protected UUID uuid;
 
@@ -79,6 +81,9 @@ public class Entity {
 
     protected EntityDefinition<?> definition;
 
+    /**
+     * Indicates if the entity has been initialized and spawned
+     */
     protected boolean valid;
 
     /* Metadata about this specific entity */
@@ -90,7 +95,8 @@ public class Entity {
     protected String nametag = "";
     /* Metadata end */
 
-    protected LongOpenHashSet passengers = new LongOpenHashSet();
+    protected List<Entity> passengers = Collections.emptyList();
+    protected Entity vehicle;
     /**
      * A container to store temporary metadata before it's sent to Bedrock.
      */
@@ -109,7 +115,7 @@ public class Entity {
     @Setter(AccessLevel.PROTECTED) // For players
     private boolean flagsDirty = false;
 
-    public Entity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         this.session = session;
 
         this.entityId = entityId;
@@ -181,11 +187,11 @@ public class Entity {
     public boolean despawnEntity() {
         if (!valid) return true;
 
-        for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated
-            Entity entity = session.getEntityCache().getEntityByJavaId(passenger);
-            if (entity == null) continue;
-            entity.setFlag(EntityFlag.RIDING, false);
-            entity.updateBedrockMetadata();
+        for (Entity passenger : passengers) { // Make sure all passengers on the despawned entity are updated
+            if (passenger == null) continue;
+            passenger.setVehicle(null);
+            passenger.setFlag(EntityFlag.RIDING, false);
+            passenger.updateBedrockMetadata();
         }
 
         RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
@@ -369,9 +375,7 @@ public class Entity {
     /**
      * Usually used for bounding box and not animation.
      */
-    public void setPose(EntityMetadata<Pose, ?> entityMetadata) {
-        Pose pose = entityMetadata.getValue();
-
+    public void setPose(Pose pose) {
         setFlag(EntityFlag.SLEEPING, pose.equals(Pose.SLEEPING));
         // Triggered when crawling
         setFlag(EntityFlag.SWIMMING, pose.equals(Pose.SWIMMING));
@@ -387,11 +391,15 @@ public class Entity {
         setBoundingBoxWidth(definition.width());
     }
 
-    public void setBoundingBoxHeight(float height) {
+    public boolean setBoundingBoxHeight(float height) {
         if (height != boundingBoxHeight) {
             boundingBoxHeight = height;
             dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
+
+            updatePassengerOffsets();
+            return true;
         }
+        return false;
     }
 
     public void setBoundingBoxWidth(float width) {
@@ -435,6 +443,30 @@ public class Entity {
         return Vector3f.from(pitch, headYaw, yaw);
     }
 
+    /**
+     * Update the mount offsets of each passenger on this vehicle
+     */
+    protected void updatePassengerOffsets() {
+        for (Entity passenger : passengers) {
+            if (passenger != null) {
+                boolean rider = passengers.get(0) == this;
+                EntityUtils.updateMountOffset(passenger, this, rider, true, passengers.size() > 1);
+                passenger.updateBedrockMetadata();
+            }
+        }
+    }
+
+    /**
+     * Update this entity's mount offset
+     */
+    protected void updateMountOffset() {
+        if (vehicle != null) {
+            boolean rider = vehicle.getPassengers().get(0) == this;
+            EntityUtils.updateMountOffset(this, vehicle, rider, true, vehicle.getPassengers().size() > 1);
+            updateBedrockMetadata();
+        }
+    }
+
     @SuppressWarnings("unchecked")
     public <I extends Entity> I as(Class<I> entityClass) {
         return entityClass.isInstance(this) ? (I) this : null;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/EvokerFangsEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/EvokerFangsEntity.java
new file mode 100644
index 000000000..f9ef2c252
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/EvokerFangsEntity.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.entity.type;
+
+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.packet.PlaySoundPacket;
+import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class EvokerFangsEntity extends Entity implements Tickable {
+    private int limitedLife = 22;
+    private boolean attackStarted = false;
+
+    public EvokerFangsEntity(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);
+        // As of 1.18.2 Bedrock, this line is required for the entity to be visible
+        // 22 is the starting number on Java Edition
+        dirtyMetadata.put(EntityData.LIMITED_LIFE, this.limitedLife);
+    }
+
+    @Override
+    public void tick() {
+        if (attackStarted) {
+            if (--this.limitedLife > 0 && this.limitedLife % 2 == 0) { // Matches Bedrock behavior
+                dirtyMetadata.put(EntityData.LIMITED_LIFE, this.limitedLife);
+                updateBedrockMetadata();
+            }
+        }
+    }
+
+    public void setAttackStarted() {
+        this.attackStarted = true;
+        if (!getFlag(EntityFlag.SILENT)) {
+            // Play the chomp sound
+            PlaySoundPacket packet = new PlaySoundPacket();
+            packet.setPosition(this.position);
+            packet.setSound("mob.evocation_fangs.attack");
+            packet.setVolume(1.0f);
+            packet.setPitch(ThreadLocalRandom.current().nextFloat() * 0.2f + 0.85f);
+            session.sendUpstreamPacket(packet);
+        }
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
index 8196d03ff..1c35ff172 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
@@ -32,7 +32,7 @@ import org.geysermc.geyser.session.GeyserSession;
 
 public class ExpOrbEntity extends Entity {
 
-    public ExpOrbEntity(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position) {
+    public ExpOrbEntity(GeyserSession session, int amount, int entityId, long geyserId, Vector3f position) {
         super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
 
         this.dirtyMetadata.put(EntityData.EXPERIENCE_VALUE, amount);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java
index 1f690036f..b79062ba8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FallingBlockEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class FallingBlockEntity extends Entity {
 
-    public FallingBlockEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
+    public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
         super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
 
         this.dirtyMetadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java
index 52796d67b..7350d55d5 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireballEntity.java
@@ -39,7 +39,7 @@ public class FireballEntity extends ThrowableEntity {
      */
     protected int futureTicks = 3;
 
-    public FireballEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public FireballEntity(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, Vector3f.ZERO, yaw, pitch, headYaw);
 
         float magnitude = motion.length();
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java
index 075178b55..e9d36d796 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java
@@ -50,7 +50,7 @@ import java.util.UUID;
 
 public class FireworkEntity extends Entity {
 
-    public FireworkEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public FireworkEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
index b5774bd78..ed39c7736 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
@@ -50,13 +50,13 @@ public class FishingHookEntity extends ThrowableEntity {
     private boolean inWater = false;
 
     @Getter
-    private final boolean isOwnerSessionPlayer;
+    private final long bedrockOwnerId;
     @Getter
     private long bedrockTargetId;
 
     private final BoundingBox boundingBox;
 
-    public FishingHookEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
+    public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
         super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
 
         this.boundingBox = new BoundingBox(0.125, 0.125, 0.125, 0.25, 0.25, 0.25);
@@ -66,25 +66,13 @@ public class FishingHookEntity extends ThrowableEntity {
         // so that it can be handled by moveAbsoluteImmediate.
         setBoundingBoxHeight(128);
 
-        isOwnerSessionPlayer = owner.getGeyserId() == session.getPlayerEntity().getGeyserId();
-        this.dirtyMetadata.put(EntityData.OWNER_EID, owner.getGeyserId());
-    }
-
-    @Override
-    public void spawnEntity() {
-
-        super.spawnEntity();
+        this.bedrockOwnerId = owner.getGeyserId();
+        this.dirtyMetadata.put(EntityData.OWNER_EID, this.bedrockOwnerId);
     }
 
     public void setHookedEntity(IntEntityMetadata entityMetadata) {
         int hookedEntityId = entityMetadata.getPrimitiveValue() - 1;
-        Entity entity;
-        if (session.getPlayerEntity().getEntityId() == hookedEntityId) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
         if (entity != null) {
             bedrockTargetId = entity.getGeyserId();
             dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
index ab34cb751..39e1bede2 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
@@ -37,7 +37,7 @@ import java.util.UUID;
 public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
     private boolean hasFuel = false;
 
-    public FurnaceMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public FurnaceMinecartEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
index dd98f9aba..efa55b388 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
@@ -46,7 +46,7 @@ public class ItemEntity extends ThrowableEntity {
 
     private int waterLevel = -1;
 
-    public ItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ItemEntity(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);
     }
 
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 0f73de739..0715f864e 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
@@ -77,7 +77,7 @@ public class ItemFrameEntity extends Entity {
      */
     private boolean changed = true;
 
-    public ItemFrameEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
+    public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
         super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
 
         NbtMapBuilder blockBuilder = NbtMap.builder()
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java
index 63e964a55..a18cc28d4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/LeashKnotEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class LeashKnotEntity extends Entity {
 
-    public LeashKnotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public LeashKnotEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         // Position is incorrect by default
         super(session, entityId, geyserId, uuid, definition, position.add(0.5f, 0.25f, 0.5f), motion, yaw, pitch, headYaw);
     }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LightningEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LightningEntity.java
index 1f5af0492..94fe56fb9 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/LightningEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/LightningEntity.java
@@ -35,7 +35,7 @@ import java.util.concurrent.ThreadLocalRandom;
 
 public class LightningEntity extends Entity {
 
-    public LightningEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public LightningEntity(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);
     }
 
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 2aff7f9e1..77654fd17 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
@@ -80,7 +80,7 @@ public class LivingEntity extends Entity {
      */
     private boolean isMaxFrozenState = false;
 
-    public LivingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java
index ffb5e4018..5b8234245 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/MinecartEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class MinecartEntity extends Entity {
 
-    public MinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public MinecartEntity(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.add(0d, definition.offset(), 0d), motion, yaw, pitch, headYaw);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
index e97bb7090..02ee8d1cb 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
@@ -38,7 +38,7 @@ public class PaintingEntity extends Entity {
     private final PaintingType paintingName;
     private final int direction;
 
-    public PaintingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
+    public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
         super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
         this.paintingName = paintingName;
         this.direction = direction;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
index 2cd4cf3f6..96a3eea0e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
 
-    public SpawnerMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SpawnerMinecartEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
index e7edd32d5..c0cb87971 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
@@ -38,7 +38,7 @@ import java.util.UUID;
 public class TNTEntity extends Entity implements Tickable {
     private int currentTick;
 
-    public TNTEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TNTEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java
index d68779c9f..ab219501d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableEntity.java
@@ -44,7 +44,7 @@ public class ThrowableEntity extends Entity implements Tickable {
 
     protected Vector3f lastJavaPosition;
 
-    public ThrowableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ThrowableEntity(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);
         this.lastJavaPosition = position;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java
index 2cee252ec..c85aeeff8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrowableItemEntity.java
@@ -44,7 +44,7 @@ public class ThrowableItemEntity extends ThrowableEntity {
     private int age;
     private boolean invisible;
 
-    public ThrowableItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ThrowableItemEntity(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);
         setFlag(EntityFlag.INVISIBLE, true);
         invisible = false;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
index 3b4d5674a..204a0171e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java
@@ -44,7 +44,7 @@ import java.util.UUID;
 public class ThrownPotionEntity extends ThrowableItemEntity {
     private static final EnumSet<Potion> NON_ENCHANTED_POTIONS = EnumSet.of(Potion.WATER, Potion.MUNDANE, Potion.THICK, Potion.AWKWARD);
 
-    public ThrownPotionEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ThrownPotionEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java
index a60c0ab33..28289acdf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java
@@ -39,7 +39,7 @@ import java.util.UUID;
  */
 public class TippedArrowEntity extends AbstractArrowEntity {
 
-    public TippedArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TippedArrowEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TridentEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TridentEntity.java
index 65591fb50..0ab462669 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/TridentEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/TridentEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class TridentEntity extends AbstractArrowEntity {
 
-    public TridentEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TridentEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java
index f645fae34..d96aa1ef7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/WitherSkullEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 public class WitherSkullEntity extends FireballEntity {
     private boolean isCharged;
 
-    public WitherSkullEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public WitherSkullEntity(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);
 
         this.futureTicks = 1;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java
index 8fedce1e7..cc293c54a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AbstractFishEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class AbstractFishEntity extends WaterEntity {
 
-    public AbstractFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractFishEntity(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);
 
         setFlag(EntityFlag.CAN_SWIM, true);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java
index b04247a7a..1961aa36b 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AgeableEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class AgeableEntity extends CreatureEntity {
 
-    public AgeableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AgeableEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
index 693a0cd46..177c46f2f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class AmbientEntity extends MobEntity {
 
-    public AmbientEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AmbientEntity(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);
     }
 }
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 fb459bf54..0a8a01ae8 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
@@ -78,7 +78,7 @@ public class ArmorStandEntity extends LivingEntity {
      */
     private boolean positionUpdateRequired = false;
 
-    public ArmorStandEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ArmorStandEntity(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);
     }
 
@@ -146,13 +146,14 @@ public class ArmorStandEntity extends LivingEntity {
         isMarker = (xd & 0x10) == 0x10;
         if (oldIsMarker != isMarker) {
             if (isMarker) {
-                dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
-                dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
+                setBoundingBoxWidth(0.0f);
+                setBoundingBoxHeight(0.0f);
                 dirtyMetadata.put(EntityData.SCALE, 0f);
             } else {
                 toggleSmallStatus();
             }
 
+            updateMountOffset();
             updateSecondEntityStatus(false);
         }
 
@@ -376,8 +377,8 @@ public class ArmorStandEntity extends LivingEntity {
      * If this armor stand is not a marker, set its bounding box size and scale.
      */
     private void toggleSmallStatus() {
-        dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : definition.width());
-        dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : definition.height());
+        setBoundingBoxWidth(isSmall ? 0.25f : definition.width());
+        setBoundingBoxHeight(isSmall ? 0.9875f : definition.height());
         dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java
index 0a72a431e..8f8061acf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/BatEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class BatEntity extends AmbientEntity {
 
-    public BatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public BatEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/CreatureEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/CreatureEntity.java
index b5e7557da..a6a2b03da 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/CreatureEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/CreatureEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class CreatureEntity extends MobEntity {
 
-    public CreatureEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public CreatureEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/FlyingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/FlyingEntity.java
index 91f839bc3..07060afba 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/FlyingEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/FlyingEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class FlyingEntity extends MobEntity {
 
-    public FlyingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public FlyingEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/GlowSquidEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/GlowSquidEntity.java
index b5950b7bc..51c3f49b5 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/GlowSquidEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/GlowSquidEntity.java
@@ -32,7 +32,7 @@ import org.geysermc.geyser.session.GeyserSession;
 import java.util.UUID;
 
 public class GlowSquidEntity extends SquidEntity {
-    public GlowSquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GlowSquidEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/GolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/GolemEntity.java
index eb94e1406..16534791d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/GolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/GolemEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class GolemEntity extends CreatureEntity {
 
-    public GolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GolemEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
index f86392ed3..4dac986d1 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class IronGolemEntity extends GolemEntity {
 
-    public IronGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public IronGolemEntity(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);
         // Indicate that we should show cracks through a resource pack
         setFlag(EntityFlag.BRIBED, true);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MagmaCubeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MagmaCubeEntity.java
index 03cf9f3dc..40c99283c 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MagmaCubeEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MagmaCubeEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class MagmaCubeEntity extends SlimeEntity {
 
-    public MagmaCubeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public MagmaCubeEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
index e82b813d7..d2c9bf3df 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
@@ -43,7 +43,7 @@ public class MobEntity extends LivingEntity {
     @Getter
     private long leashHolderBedrockId;
 
-    public MobEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public MobEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java
index 100ed764d..98c734e87 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SlimeEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class SlimeEntity extends MobEntity {
 
-    public SlimeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SlimeEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
index 1d8375529..22a36c191 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SnowGolemEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class SnowGolemEntity extends GolemEntity {
 
-    public SnowGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SnowGolemEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
index b0e2fcb9e..ebe103246 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
@@ -41,7 +41,7 @@ public class SquidEntity extends WaterEntity implements Tickable {
 
     private boolean inWater;
 
-    public SquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SquidEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
index acacd1f52..7da07cceb 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class WaterEntity extends CreatureEntity {
 
-    public WaterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public WaterEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
index c7c15b288..be47014ab 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AnimalEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class AnimalEntity extends AgeableEntity {
 
-    public AnimalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AnimalEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
index 4dfa5fa8d..de8004035 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
@@ -37,7 +37,7 @@ import org.geysermc.geyser.registry.type.ItemMapping;
 import java.util.UUID;
 
 public class AxolotlEntity extends AnimalEntity {
-    public AxolotlEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AxolotlEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
index 7f9ec4255..579d36b00 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/BeeEntity.java
@@ -40,7 +40,7 @@ import java.util.UUID;
 
 public class BeeEntity extends AnimalEntity {
 
-    public BeeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public BeeEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
index 506714dbc..2fe648de3 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/ChickenEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class ChickenEntity extends AnimalEntity {
 
-    public ChickenEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ChickenEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
index 127a70a0f..7d0a29d7e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/FoxEntity.java
@@ -38,7 +38,7 @@ import java.util.UUID;
 
 public class FoxEntity extends AnimalEntity {
 
-    public FoxEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public FoxEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
index 708a95134..b04939f6d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/GoatEntity.java
@@ -41,7 +41,7 @@ public class GoatEntity extends AnimalEntity {
     @Getter
     private boolean isScreamer;
 
-    public GoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GoatEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
index ed0feed97..5ac9e8bbd 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
@@ -29,16 +29,15 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
 import com.nukkitx.math.vector.Vector3f;
 import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.registry.type.ItemMapping;
-import org.geysermc.geyser.util.DimensionUtils;
+import org.geysermc.geyser.session.GeyserSession;
 
 import java.util.UUID;
 
 public class HoglinEntity extends AnimalEntity {
     private boolean isImmuneToZombification;
 
-    public HoglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public HoglinEntity(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);
     }
 
@@ -50,7 +49,7 @@ public class HoglinEntity extends AnimalEntity {
 
     @Override
     protected boolean isShaking() {
-        return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
+        return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
     }
 
     @Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
index 15473c8ac..128b7abac 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/MooshroomEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class MooshroomEntity extends AnimalEntity {
 
-    public MooshroomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public MooshroomEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
index 5244e3538..0ce4f4213 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/OcelotEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class OcelotEntity extends AnimalEntity {
 
-    public OcelotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public OcelotEntity(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);
     }
 
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 7548ccef1..4ccef13ad 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
@@ -42,7 +42,7 @@ public class PandaEntity extends AnimalEntity {
     private int mainGene;
     private int hiddenGene;
 
-    public PandaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PandaEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
index 0be4c78f1..6e772bf18 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class PigEntity extends AnimalEntity {
 
-    public PigEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PigEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
index 727804dbc..15eabc4b2 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PolarBearEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class PolarBearEntity extends AnimalEntity {
 
-    public PolarBearEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PolarBearEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java
index 66853babf..8fe8d8d4b 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PufferFishEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class PufferFishEntity extends AbstractFishEntity {
 
-    public PufferFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PufferFishEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
index a1d80ac72..be2448ce8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/RabbitEntity.java
@@ -38,7 +38,7 @@ import java.util.UUID;
 
 public class RabbitEntity extends AnimalEntity {
 
-    public RabbitEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public RabbitEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
index 757c5b574..a5e822f3f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/SheepEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class SheepEntity extends AnimalEntity {
 
-    public SheepEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SheepEntity(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);
     }
 
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 d684fba06..79290faf0 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
@@ -39,7 +39,7 @@ public class StriderEntity extends AnimalEntity {
 
     private boolean isCold = false;
 
-    public StriderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public StriderEntity(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);
 
         setFlag(EntityFlag.FIRE_IMMUNE, true);
@@ -60,12 +60,8 @@ public class StriderEntity extends AnimalEntity {
         // Needs to copy the parent state
         if (getFlag(EntityFlag.RIDING)) {
             boolean parentShaking = false;
-            //TODO optimize
-            for (Entity ent : session.getEntityCache().getEntities().values()) {
-                if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) {
-                    parentShaking = ent.getFlag(EntityFlag.SHAKING);
-                    break;
-                }
+            if (vehicle instanceof StriderEntity) {
+                parentShaking = vehicle.getFlag(EntityFlag.SHAKING);
             }
     
             setFlag(EntityFlag.BREATHING, !parentShaking);
@@ -76,10 +72,9 @@ public class StriderEntity extends AnimalEntity {
         }
 
         // Update the passengers if we have any
-        for (long passenger : passengers) {
-            Entity passengerEntity = session.getEntityCache().getEntityByJavaId(passenger);
-            if (passengerEntity != null) {
-                passengerEntity.updateBedrockMetadata();
+        for (Entity passenger : passengers) {
+            if (passenger != null) {
+                passenger.updateBedrockMetadata();
             }
         }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java
index b883c91a9..c1f2f4326 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TropicalFishEntity.java
@@ -48,7 +48,7 @@ public class TropicalFishEntity extends AbstractFishEntity {
     private static final List<String> VARIANT_NAMES = ImmutableList.of("kob", "sunstreak", "snooper", "dasher", "brinely", "spotty", "flopper", "stripey", "glitter", "blockfish", "betty", "clayfish");
     private static final List<String> COLOR_NAMES = ImmutableList.of("white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black");
 
-    public TropicalFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TropicalFishEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
index e892d7d5e..ac3ce7365 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class TurtleEntity extends AnimalEntity {
 
-    public TurtleEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TurtleEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
index 7d0a3cf9a..2a5b13032 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/AbstractHorseEntity.java
@@ -51,7 +51,7 @@ public class AbstractHorseEntity extends AnimalEntity {
     private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
             "golden_carrot", "sugar", "apple", "wheat", "hay_block");
 
-    public AbstractHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractHorseEntity(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);
 
         // Specifies the size of the entity's inventory. Required to place slots in the entity.
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
index ccf30dbc8..61fdb6c4d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/ChestedHorseEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class ChestedHorseEntity extends AbstractHorseEntity {
 
-    public ChestedHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ChestedHorseEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java
index 31b5b7890..9389684b6 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/HorseEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class HorseEntity extends AbstractHorseEntity {
 
-    public HorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public HorseEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
index c18778c81..8d374be17 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/LlamaEntity.java
@@ -38,7 +38,7 @@ import java.util.UUID;
 
 public class LlamaEntity extends ChestedHorseEntity {
 
-    public LlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public LlamaEntity(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);
 
         dirtyMetadata.put(EntityData.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/TraderLlamaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/TraderLlamaEntity.java
index 770d30a05..95a65ab4e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/TraderLlamaEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/horse/TraderLlamaEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class TraderLlamaEntity extends LlamaEntity {
 
-    public TraderLlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TraderLlamaEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
index 5538621d9..0b72750d5 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/CatEntity.java
@@ -41,7 +41,7 @@ public class CatEntity extends TameableEntity {
 
     private byte collarColor;
 
-    public CatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public CatEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
index 05f0a6ad5..53524e7ba 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/ParrotEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class ParrotEntity extends TameableEntity {
 
-    public ParrotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ParrotEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
index d12839e92..23750790e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
@@ -46,7 +46,7 @@ public class TameableEntity extends AnimalEntity {
     @Getter
     protected long ownerBedrockId;
 
-    public TameableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public TameableEntity(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);
     }
 
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 13bb8e17d..a5c932706 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
@@ -49,7 +49,7 @@ public class WolfEntity extends TameableEntity {
 
     private byte collarColor;
 
-    public WolfEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public WolfEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
index 7981c9b23..1499b2826 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class AbstractMerchantEntity extends AgeableEntity {
 
-    public AbstractMerchantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractMerchantEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
index 012fb05f2..50627f2a0 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
@@ -88,7 +88,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
     @Getter
     private boolean canTradeWith;
 
-    public VillagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public VillagerEntity(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);
     }
 
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 ae13cfeae..d76d85dbc 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
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class AbstractSkeletonEntity extends MonsterEntity {
 
-    public AbstractSkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractSkeletonEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
index 2f315368f..526ff41ac 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
@@ -30,14 +30,13 @@ import com.nukkitx.math.vector.Vector3f;
 import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
 import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.DimensionUtils;
 
 import java.util.UUID;
 
 public class BasePiglinEntity extends MonsterEntity {
     private boolean isImmuneToZombification;
 
-    public BasePiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public BasePiglinEntity(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);
     }
 
@@ -49,6 +48,6 @@ public class BasePiglinEntity extends MonsterEntity {
 
     @Override
     protected boolean isShaking() {
-        return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
+        return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java
index 2303f8091..f52a237a3 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BlazeEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class BlazeEntity extends MonsterEntity {
 
-    public BlazeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public BlazeEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
index f1e0b6a65..b3d530a3e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreeperEntity.java
@@ -41,7 +41,7 @@ public class CreeperEntity extends MonsterEntity {
      */
     private boolean ignitedByFlintAndSteel = false;
 
-    public CreeperEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public CreeperEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ElderGuardianEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ElderGuardianEntity.java
index 9c237f117..db33e17bd 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ElderGuardianEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ElderGuardianEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class ElderGuardianEntity extends GuardianEntity {
 
-    public ElderGuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ElderGuardianEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java
index f49b51e6c..6dd5f3765 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonEntity.java
@@ -79,7 +79,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
     private float wingPosition;
     private float lastWingPosition;
 
-    public EnderDragonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public EnderDragonEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonPartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonPartEntity.java
index 7cd4bb6cf..3e70f9483 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonPartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EnderDragonPartEntity.java
@@ -34,7 +34,7 @@ import org.geysermc.geyser.session.GeyserSession;
 
 public class EnderDragonPartEntity extends Entity {
 
-    public EnderDragonPartEntity(GeyserSession session, long entityId, long geyserId, float width, float height) {
+    public EnderDragonPartEntity(GeyserSession session, int entityId, long geyserId, float width, float height) {
         super(session, entityId, geyserId, null, EntityDefinitions.ENDER_DRAGON_PART, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
 
         dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, width);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java
index 469f48521..7b06274df 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/EndermanEntity.java
@@ -39,7 +39,7 @@ import java.util.UUID;
 
 public class EndermanEntity extends MonsterEntity {
 
-    public EndermanEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public EndermanEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java
index 845a281d9..455da559c 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GhastEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class GhastEntity extends FlyingEntity {
 
-    public GhastEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GhastEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java
index 6dd27cc39..3b32924bd 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GiantEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class GiantEntity extends MonsterEntity {
 
-    public GiantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GiantEntity(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);
 
         dirtyMetadata.put(EntityData.SCALE, 6f);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java
index 0190f3c60..41bb685ff 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/GuardianEntity.java
@@ -36,19 +36,13 @@ import java.util.UUID;
 
 public class GuardianEntity extends MonsterEntity {
 
-    public GuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public GuardianEntity(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 void setGuardianTarget(IntEntityMetadata entityMetadata) {
         int entityId = entityMetadata.getPrimitiveValue();
-        Entity entity;
-        if (session.getPlayerEntity().getEntityId() == entityId) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(entityId);
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(entityId);
         if (entity != null) {
             dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
         } else {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/MonsterEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/MonsterEntity.java
index fad45f982..5285c3699 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/MonsterEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/MonsterEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class MonsterEntity extends CreatureEntity {
 
-    public MonsterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public MonsterEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java
index 8d3ccc71f..be0d4d4cf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PhantomEntity.java
@@ -35,7 +35,7 @@ import org.geysermc.geyser.session.GeyserSession;
 import java.util.UUID;
 
 public class PhantomEntity extends FlyingEntity {
-    public PhantomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PhantomEntity(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);
     }
 
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 b98d6eabc..4a65477ae 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
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class PiglinEntity extends BasePiglinEntity {
 
-    public PiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PiglinEntity(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);
     }
 
@@ -44,6 +44,8 @@ public class PiglinEntity extends BasePiglinEntity {
         boolean isBaby = entityMetadata.getPrimitiveValue();
         dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f);
         setFlag(EntityFlag.BABY, isBaby);
+
+        updateMountOffset();
     }
 
     public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java
index e60f81d2f..30fddfaaf 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java
@@ -39,7 +39,7 @@ import java.util.UUID;
 
 public class ShulkerEntity extends GolemEntity {
 
-    public ShulkerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ShulkerEntity(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);
         // Indicate that invisibility should be fixed through the resource pack
         setFlag(EntityFlag.BRIBED, true);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java
index b1f6939aa..ac2c1971a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SkeletonEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 public class SkeletonEntity extends AbstractSkeletonEntity {
     private boolean convertingToStray = false;
 
-    public SkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SkeletonEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java
index 4f7b02d73..6eda40591 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/SpiderEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class SpiderEntity extends MonsterEntity {
 
-    public SpiderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SpiderEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java
index 938b18022..243691533 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/VexEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class VexEntity extends MonsterEntity {
 
-    public VexEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public VexEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java
index 17da0a611..6156cf410 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WitherEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
 
 public class WitherEntity extends MonsterEntity {
 
-    public WitherEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public WitherEntity(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);
     }
 
@@ -60,15 +60,11 @@ public class WitherEntity extends MonsterEntity {
 
     private void setTargetId(EntityData entityData, IntEntityMetadata entityMetadata) {
         int entityId = entityMetadata.getPrimitiveValue();
-        Entity entity;
-        if (session.getPlayerEntity().getEntityId() == entityId) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(entityId);
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(entityId);
         if (entity != null) {
             dirtyMetadata.put(entityData, entity.getGeyserId());
+        } else {
+            dirtyMetadata.put(entityData, (long) 0);
         }
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
index f0fe101da..1d43b9ea7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
@@ -36,13 +36,23 @@ import java.util.UUID;
 
 public class ZoglinEntity extends MonsterEntity {
 
-    public ZoglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ZoglinEntity(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 void setBaby(BooleanEntityMetadata entityMetadata) {
         boolean isBaby = entityMetadata.getPrimitiveValue();
-        dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f);
-        setFlag(EntityFlag.BABY, isBaby);
+        if (isBaby != getFlag(EntityFlag.BABY)) {
+            dirtyMetadata.put(EntityData.SCALE, isBaby ? .55f : 1f);
+            setFlag(EntityFlag.BABY, isBaby);
+
+            updatePassengerOffsets();
+        }
+    }
+
+    @Override
+    public float getBoundingBoxHeight() {
+        float scale = getFlag(EntityFlag.BABY) ? 0.55f : 1f;
+        return scale * definition.height();
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
index 9e3301b48..2ad31f8a4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
@@ -37,7 +37,7 @@ import java.util.UUID;
 public class ZombieEntity extends MonsterEntity {
     private boolean convertingToDrowned = false;
 
-    public ZombieEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ZombieEntity(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);
     }
 
@@ -45,6 +45,8 @@ public class ZombieEntity extends MonsterEntity {
         boolean isBaby = entityMetadata.getPrimitiveValue();
         dirtyMetadata.put(EntityData.SCALE, isBaby ? .55f : 1.0f);
         setFlag(EntityFlag.BABY, isBaby);
+
+        updateMountOffset();
     }
 
     public void setConvertingToDrowned(BooleanEntityMetadata entityMetadata) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
index 54a5c4506..6897f6808 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieVillagerEntity.java
@@ -40,7 +40,7 @@ import java.util.UUID;
 public class ZombieVillagerEntity extends ZombieEntity {
     private boolean isTransforming;
 
-    public ZombieVillagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ZombieVillagerEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombifiedPiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombifiedPiglinEntity.java
index 2604ce12e..9d6ab17d1 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombifiedPiglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombifiedPiglinEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class ZombifiedPiglinEntity extends ZombieEntity {
 
-    public ZombifiedPiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public ZombifiedPiglinEntity(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);
 
         setFlag(EntityFlag.FIRE_IMMUNE, true);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/AbstractIllagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/AbstractIllagerEntity.java
index 15ac1a0d9..b602fb5a4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/AbstractIllagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/AbstractIllagerEntity.java
@@ -33,7 +33,7 @@ import java.util.UUID;
 
 public class AbstractIllagerEntity extends RaidParticipantEntity {
 
-    public AbstractIllagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public AbstractIllagerEntity(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);
     }
 }
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 477d9fef7..471cc2bc0 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
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class PillagerEntity extends AbstractIllagerEntity {
 
-    public PillagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PillagerEntity(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);
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RaidParticipantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RaidParticipantEntity.java
index bd0f3ac5d..668f8ae06 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RaidParticipantEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RaidParticipantEntity.java
@@ -34,7 +34,7 @@ import java.util.UUID;
 
 public class RaidParticipantEntity extends MonsterEntity {
 
-    public RaidParticipantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public RaidParticipantEntity(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);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java
index 7c2a05de1..38d2e8822 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/SpellcasterIllagerEntity.java
@@ -40,7 +40,7 @@ public class SpellcasterIllagerEntity extends AbstractIllagerEntity {
     private static final int ATTACK_PARTICLE_COLOR = (102 << 16) | (77 << 8) | 89;
     private static final int WOLOLO_PARTICLE_COLOR = (179 << 16) | (128 << 8) | 51;
 
-    public SpellcasterIllagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public SpellcasterIllagerEntity(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);
         // OptionalPack usage
         setFlag(EntityFlag.BRIBED, this.definition == EntityDefinitions.ILLUSIONER);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
index a3b85dc73..180bedca2 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
@@ -35,7 +35,7 @@ import java.util.UUID;
 
 public class VindicatorEntity extends AbstractIllagerEntity {
 
-    public VindicatorEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public VindicatorEntity(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);
     }
 
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 1d59b83db..cc33854cc 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
@@ -65,6 +65,8 @@ import java.util.concurrent.TimeUnit;
 
 @Getter @Setter
 public class PlayerEntity extends LivingEntity {
+    public static final float SNEAKING_POSE_HEIGHT = 1.5f;
+
     private GameProfile profile;
     private String username;
     private boolean playerList = true;  // Player is in the player list
@@ -80,7 +82,7 @@ public class PlayerEntity extends LivingEntity {
      */
     private ParrotEntity rightParrot;
 
-    public PlayerEntity(GeyserSession session, long entityId, long geyserId, GameProfile gameProfile, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+    public PlayerEntity(GeyserSession session, int entityId, long geyserId, GameProfile gameProfile, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
         super(session, entityId, geyserId, gameProfile.getId(), EntityDefinitions.PLAYER, position, motion, yaw, pitch, headYaw);
 
         profile = gameProfile;
@@ -123,14 +125,6 @@ public class PlayerEntity extends LivingEntity {
 
         setFlagsDirty(false);
 
-        long linkedEntityId = session.getEntityCache().getCachedPlayerEntityLink(entityId);
-        if (linkedEntityId != -1) {
-            Entity linkedEntity = session.getEntityCache().getEntityByJavaId(linkedEntityId);
-            if (linkedEntity != null) {
-                addPlayerPacket.getEntityLinks().add(new EntityLinkData(linkedEntity.getGeyserId(), geyserId, EntityLinkData.Type.RIDER, false, false));
-            }
-        }
-
         valid = true;
         session.sendUpstreamPacket(addPlayerPacket);
     }
@@ -389,7 +383,7 @@ public class PlayerEntity extends LivingEntity {
     protected void setDimensions(Pose pose) {
         float height;
         switch (pose) {
-            case SNEAKING -> height = 1.5f;
+            case SNEAKING -> height = SNEAKING_POSE_HEIGHT;
             case FALL_FLYING, SPIN_ATTACK, SWIMMING -> height = 0.6f;
             default -> {
                 super.setDimensions(pose);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
index dff9fbfa2..9b1fb8263 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
@@ -28,7 +28,6 @@ package org.geysermc.geyser.entity.type.player;
 import com.github.steveice10.mc.auth.data.GameProfile;
 import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
 import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
 import com.nukkitx.math.vector.Vector3f;
@@ -70,13 +69,10 @@ public class SessionPlayerEntity extends PlayerEntity {
      */
     private int fakeTradeXp;
 
-    private final GeyserSession session;
-
     public SessionPlayerEntity(GeyserSession session) {
-        super(session, 1, 1, new GameProfile(UUID.randomUUID(), "unknown"), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
+        super(session, -1, 1, new GameProfile(UUID.randomUUID(), "unknown"), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
 
         valid = true;
-        this.session = session;
     }
 
     @Override
@@ -92,7 +88,7 @@ public class SessionPlayerEntity extends PlayerEntity {
 
     @Override
     public void setPosition(Vector3f position) {
-        if (session != null) { // null during entity initialization
+        if (valid) { // Don't update during session init
             session.getCollisionManager().updatePlayerBoundingBox(position);
         }
         super.setPosition(position);
@@ -117,9 +113,20 @@ public class SessionPlayerEntity extends PlayerEntity {
     }
 
     @Override
-    public void setPose(EntityMetadata<Pose, ?> entityMetadata) {
-        super.setPose(entityMetadata);
-        session.setPose(entityMetadata.getValue());
+    public boolean setBoundingBoxHeight(float height) {
+        if (super.setBoundingBoxHeight(height)) {
+            if (valid) { // Don't update during session init
+                session.getCollisionManager().updatePlayerBoundingBox();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void setPose(Pose pose) {
+        super.setPose(pose);
+        session.setPose(pose);
         refreshSpeed = true;
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
index 5bd72182f..7a204ba4e 100644
--- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
@@ -362,7 +362,22 @@ public class CollisionManager {
      * @return true if the block located at the player's floor position plus 1 would intersect with the player,
      * were they not sneaking
      */
-    public boolean isUnderSlab() {
+    public boolean mustPlayerSneakHere() {
+        return checkPose(EntityDefinitions.PLAYER.height());
+    }
+
+    /**
+     * @return true if the block located at the player's floor position plus 1 would intersect with the player,
+     * were they not crawling
+     */
+    public boolean mustPlayerCrawlHere() {
+        return checkPose(PlayerEntity.SNEAKING_POSE_HEIGHT);
+    }
+
+    /**
+     * @param height check and see if this height is invalid in the current player position
+     */
+    private boolean checkPose(float height) {
         Vector3i position = session.getPlayerEntity().getPosition().toInt();
         BlockCollision collision = BlockUtils.getCollisionAt(session, position);
         if (collision != null) {
@@ -370,7 +385,7 @@ public class CollisionManager {
             // at the current location.
             double originalY = playerBoundingBox.getMiddleY();
             double originalHeight = playerBoundingBox.getSizeY();
-            double standingY = originalY - (originalHeight / 2.0) + (EntityDefinitions.PLAYER.height() / 2.0);
+            double standingY = originalY - (originalHeight / 2.0) + (height / 2.0);
 
             playerBoundingBox.setSizeY(EntityDefinitions.PLAYER.height());
             playerBoundingBox.setMiddleY(standingY);
diff --git a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java
index d2ebbe4ac..24377698e 100644
--- a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java
+++ b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java
@@ -25,6 +25,7 @@
 
 package org.geysermc.geyser.ping;
 
+import javax.annotation.Nullable;
 import java.net.Inet4Address;
 import java.net.InetSocketAddress;
 
@@ -38,6 +39,7 @@ public interface IGeyserPingPassthrough {
      *
      * @return string of the MOTD
      */
+    @Nullable
     default GeyserPingInfo getPingInformation() {
         return this.getPingInformation(new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69));
     }
@@ -48,6 +50,7 @@ public interface IGeyserPingPassthrough {
      * @param inetSocketAddress the ip address of the client pinging the server
      * @return string of the MOTD
      */
+    @Nullable
     GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress);
 
 }
diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
index 2e3368356..c7e2018dd 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -42,9 +42,7 @@ import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
 import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic;
 import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
 import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket;
 import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
 import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
 import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket;
 import com.github.steveice10.packetlib.BuiltinFlags;
@@ -68,7 +66,6 @@ import it.unimi.dsi.fastutil.ints.*;
 import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.ObjectIterator;
 import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
 import lombok.AccessLevel;
 import lombok.Getter;
@@ -167,7 +164,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
     private final TagCache tagCache;
     private final WorldCache worldCache;
 
-    private final Int2ObjectMap<TeleportCache> teleportMap = new Int2ObjectOpenHashMap<>();
+    @Setter
+    private TeleportCache unconfirmedTeleport;
 
     private final WorldBorder worldBorder;
     /**
@@ -304,6 +302,12 @@ public class GeyserSession implements GeyserConnection, CommandSender {
      */
     @Setter
     private String dimension = DimensionUtils.OVERWORLD;
+    /**
+     * Whether piglins and hoglins are safe from conversion in this dimension.
+     * This controls if they have the shaking effect applied in the dimension.
+     */
+    @Setter
+    private boolean dimensionPiglinSafe;
 
     @Setter
     private int breakingBlock;
@@ -333,9 +337,6 @@ public class GeyserSession implements GeyserConnection, CommandSender {
     @Setter
     private Vector3f lastInteractionPlayerPosition = Vector3f.ZERO;
 
-    @Setter
-    private Entity ridingVehicleEntity;
-
     /**
      * The entity that the client is currently looking at.
      */
@@ -1058,16 +1059,24 @@ public class GeyserSession implements GeyserConnection, CommandSender {
     }
 
     private void setSneakingPose(boolean sneaking) {
-        this.pose = sneaking ? Pose.SNEAKING : Pose.STANDING;
-        playerEntity.setBoundingBoxHeight(sneaking ? 1.5f : playerEntity.getDefinition().height());
+        if (this.pose == Pose.SNEAKING && !sneaking) {
+            this.pose = Pose.STANDING;
+            playerEntity.setBoundingBoxHeight(playerEntity.getDefinition().height());
+        } else if (sneaking) {
+            this.pose = Pose.SNEAKING;
+            playerEntity.setBoundingBoxHeight(1.5f);
+        }
         playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
-
-        collisionManager.updatePlayerBoundingBox();
     }
 
     public void setSwimming(boolean swimming) {
-        this.pose = swimming ? Pose.SWIMMING : Pose.STANDING;
-        playerEntity.setBoundingBoxHeight(swimming ? 0.6f : playerEntity.getDefinition().height());
+        if (swimming) {
+            this.pose = Pose.SWIMMING;
+            playerEntity.setBoundingBoxHeight(0.6f);
+        } else {
+            this.pose = Pose.STANDING;
+            playerEntity.setBoundingBoxHeight(playerEntity.getDefinition().height());
+        }
         playerEntity.setFlag(EntityFlag.SWIMMING, swimming);
         playerEntity.updateBedrockMetadata();
     }
@@ -1090,7 +1099,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
     public AttributeData adjustSpeed() {
         AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED);
         if (currentPlayerSpeed != null) {
-            if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.isUnderSlab()) ||
+            if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) ||
                     (!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
                 // Either of those conditions means that Bedrock goes zoom when they shouldn't be
                 AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f);
@@ -1247,73 +1256,23 @@ public class GeyserSession implements GeyserConnection, CommandSender {
         return itemNetId.getAndIncrement();
     }
 
-    public void addTeleport(TeleportCache teleportCache) {
-        teleportMap.put(teleportCache.getTeleportConfirmId(), teleportCache);
-
-        ObjectIterator<Int2ObjectMap.Entry<TeleportCache>> it = teleportMap.int2ObjectEntrySet().iterator();
-
-        // Remove any teleports with a higher number - maybe this is a world change that reset the ID to 0?
-        while (it.hasNext()) {
-            Int2ObjectMap.Entry<TeleportCache> entry = it.next();
-            int nextID = entry.getValue().getTeleportConfirmId();
-            if (nextID > teleportCache.getTeleportConfirmId()) {
-                it.remove();
-            }
-        }
-    }
-
     public void confirmTeleport(Vector3d position) {
-        if (teleportMap.size() == 0) {
+        if (unconfirmedTeleport == null) {
             return;
         }
-        int teleportID = -1;
 
-        for (Int2ObjectMap.Entry<TeleportCache> entry : teleportMap.int2ObjectEntrySet()) {
-            if (entry.getValue().canConfirm(position)) {
-                if (entry.getValue().getTeleportConfirmId() > teleportID) {
-                    teleportID = entry.getValue().getTeleportConfirmId();
-                }
-            }
+        if (unconfirmedTeleport.canConfirm(position)) {
+            unconfirmedTeleport = null;
+            return;
         }
 
-        if (teleportID != -1) {
-            ObjectIterator<Int2ObjectMap.Entry<TeleportCache>> it = teleportMap.int2ObjectEntrySet().iterator();
-
-            // Confirm the current teleport and any earlier ones
-            while (it.hasNext()) {
-                TeleportCache entry = it.next().getValue();
-                int nextID = entry.getTeleportConfirmId();
-                if (nextID <= teleportID) {
-                    ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(nextID);
-                    sendDownstreamPacket(teleportConfirmPacket);
-                    // Servers (especially ones like Hypixel) expect exact coordinates given back to them.
-                    ServerboundMovePlayerPosRotPacket positionPacket = new ServerboundMovePlayerPosRotPacket(playerEntity.isOnGround(),
-                            entry.getX(), entry.getY(), entry.getZ(), entry.getYaw(), entry.getPitch());
-                    sendDownstreamPacket(positionPacket);
-                    it.remove();
-                    geyser.getLogger().debug("Confirmed teleport " + nextID);
-                }
-            }
-        }
-
-        if (teleportMap.size() > 0) {
-            int resendID = -1;
-            for (Int2ObjectMap.Entry<TeleportCache> entry : teleportMap.int2ObjectEntrySet()) {
-                TeleportCache teleport = entry.getValue();
-                teleport.incrementUnconfirmedFor();
-                if (teleport.shouldResend()) {
-                    if (teleport.getTeleportConfirmId() >= resendID) {
-                        resendID = teleport.getTeleportConfirmId();
-                    }
-                }
-            }
-
-            if (resendID != -1) {
-                geyser.getLogger().debug("Resending teleport " + resendID);
-                TeleportCache teleport = teleportMap.get(resendID);
-                getPlayerEntity().moveAbsolute(Vector3f.from(teleport.getX(), teleport.getY(), teleport.getZ()),
-                        teleport.getYaw(), teleport.getPitch(), playerEntity.isOnGround(), true);
-            }
+        // Resend the teleport every few packets until Bedrock responds
+        unconfirmedTeleport.incrementUnconfirmedFor();
+        if (unconfirmedTeleport.shouldResend()) {
+            unconfirmedTeleport.resetUnconfirmedFor();
+            geyser.getLogger().debug("Resending teleport " + unconfirmedTeleport.getTeleportConfirmId());
+            getPlayerEntity().moveAbsolute(Vector3f.from(unconfirmedTeleport.getX(), unconfirmedTeleport.getY(), unconfirmedTeleport.getZ()),
+                    unconfirmedTeleport.getYaw(), unconfirmedTeleport.getPitch(), playerEntity.isOnGround(), true);
         }
     }
 
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java
index 5d99ba0e3..fcf75525c 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/EntityCache.java
@@ -25,8 +25,8 @@
 
 package org.geysermc.geyser.session.cache;
 
-import it.unimi.dsi.fastutil.longs.Long2LongMap;
-import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
+import it.unimi.dsi.fastutil.ints.Int2LongMap;
+import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
 import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@@ -53,18 +53,15 @@ public class EntityCache {
      * A list of all entities that must be ticked.
      */
     private final List<Tickable> tickableEntities = new ObjectArrayList<>();
-    private final Long2LongMap entityIdTranslations = new Long2LongOpenHashMap();
+    private final Int2LongMap entityIdTranslations = new Int2LongOpenHashMap();
     private final Map<UUID, PlayerEntity> playerEntities = new Object2ObjectOpenHashMap<>();
     private final Map<UUID, BossBar> bossBars = new Object2ObjectOpenHashMap<>();
-    private final Long2LongMap cachedPlayerEntityLinks = new Long2LongOpenHashMap();
 
     @Getter
     private final AtomicLong nextEntityId = new AtomicLong(2L);
 
     public EntityCache(GeyserSession session) {
         this.session = session;
-
-        cachedPlayerEntityLinks.defaultReturnValue(-1L);
     }
 
     public void spawnEntity(Entity entity) {
@@ -112,15 +109,16 @@ public class EntityCache {
         }
 
         session.getPlayerWithCustomHeads().clear();
-        // As a precaution
-        cachedPlayerEntityLinks.clear();
     }
 
     public Entity getEntityByGeyserId(long geyserId) {
         return entities.get(geyserId);
     }
 
-    public Entity getEntityByJavaId(long javaId) {
+    public Entity getEntityByJavaId(int javaId) {
+        if (javaId == session.getPlayerEntity().getEntityId()) {
+            return session.getPlayerEntity();
+        }
         return entities.get(entityIdTranslations.get(javaId));
     }
 
@@ -160,14 +158,6 @@ public class EntityCache {
         bossBars.values().forEach(BossBar::updateBossBar);
     }
 
-    public long getCachedPlayerEntityLink(long playerId) {
-        return cachedPlayerEntityLinks.remove(playerId);
-    }
-
-    public void addCachedPlayerEntityLink(long playerId, long linkedEntityId) {
-        cachedPlayerEntityLinks.put(playerId, linkedEntityId);
-    }
-
     public List<Tickable> getTickableEntities() {
         return tickableEntities;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java
index cc9a7c09f..5eff56a97 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java
@@ -66,6 +66,10 @@ public class TeleportCache {
         unconfirmedFor++;
     }
 
+    public void resetUnconfirmedFor() {
+        unconfirmedFor = 0;
+    }
+
     public boolean shouldResend() {
         return unconfirmedFor >= RESEND_THRESHOLD;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java
index 01c5949c7..e4ba674ef 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java
@@ -151,7 +151,7 @@ public class WorldBorder {
             // Move the player back, but allow gravity to take place
             // Teleported = true makes going back better, but disconnects the player from their mounted entity
             playerEntity.moveAbsolute(Vector3f.from(playerEntity.getPosition().getX(), (newPosition.getY() - EntityDefinitions.PLAYER.offset()), playerEntity.getPosition().getZ()),
-                    playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), playerEntity.isOnGround(), session.getRidingVehicleEntity() == null);
+                    playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), playerEntity.isOnGround(), playerEntity.getVehicle() == null);
         }
         return isInWorldBorder;
     }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
index 0fd9f114f..fcd613c23 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
@@ -401,7 +401,6 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
                     break;
                 }
                 case CRAFT_RESULTS_DEPRECATED: {
-                    CraftResultsDeprecatedStackRequestActionData deprecatedCraftAction = (CraftResultsDeprecatedStackRequestActionData) action;
                     if (craftState != CraftState.RECIPE_ID) {
                         return rejectRequest(request);
                     }
@@ -453,6 +452,28 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
                     }
                     break;
                 }
+                case DROP: {
+                    // Can be replicated as of 1.18.2 Bedrock on mobile by clicking from the creative menu to outside it
+                    if (craftState != CraftState.DEPRECATED) {
+                        return rejectRequest(request);
+                    }
+
+                    DropStackRequestActionData dropAction = (DropStackRequestActionData) action;
+                    if (dropAction.getSource().getContainer() != ContainerSlotType.CREATIVE_OUTPUT || dropAction.getSource().getSlot() != 50) {
+                        return rejectRequest(request);
+                    }
+
+                    ItemStack dropStack;
+                    if (dropAction.getCount() == javaCreativeItem.getAmount()) {
+                        dropStack = javaCreativeItem;
+                    } else {
+                        // Specify custom count
+                        dropStack = new ItemStack(javaCreativeItem.getId(), dropAction.getCount(), javaCreativeItem.getNbt());
+                    }
+                    ServerboundSetCreativeModeSlotPacket creativeDropPacket = new ServerboundSetCreativeModeSlotPacket(-1, dropStack);
+                    session.sendDownstreamPacket(creativeDropPacket);
+                    break;
+                }
                 default:
                     return rejectRequest(request);
             }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
index 84ab0dc55..0d4ef3e78 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
@@ -34,14 +34,16 @@ import com.nukkitx.nbt.NbtType;
 import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
 import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.translator.text.MessageTranslator;
 import org.geysermc.geyser.registry.BlockRegistries;
 import org.geysermc.geyser.registry.type.ItemMapping;
 import org.geysermc.geyser.registry.type.ItemMappings;
-import org.geysermc.geyser.util.FileUtils;
+import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.text.MinecraftLocale;
+import org.geysermc.geyser.translator.text.MessageTranslator;
+import org.geysermc.geyser.util.FileUtils;
 
 import javax.annotation.Nonnull;
 import java.util.*;
@@ -206,15 +208,31 @@ public abstract class ItemTranslator {
         int maxDurability = mapping.getMaxDamage();
 
         if (maxDurability != 0) {
-            int durability = maxDurability - ((IntTag) newNbt.get("Damage")).getValue();
-            if (durability != maxDurability) {
-                listTag.add(new StringTag("", "§r§f" + String.format(MessageTranslator.convertMessage("item.durability", language), durability, maxDurability)));
+            Tag durabilityTag = newNbt.get("Damage");
+            if (durabilityTag instanceof IntTag) {
+                int durability = maxDurability - ((IntTag) durabilityTag).getValue();
+                if (durability != maxDurability) {
+                    Component component = Component.text()
+                            .resetStyle()
+                            .color(NamedTextColor.WHITE)
+                            .append(Component.translatable("item.durability",
+                                    Component.text(durability),
+                                    Component.text(maxDurability)))
+                            .build();
+                    listTag.add(new StringTag("", MessageTranslator.convertMessage(component, language)));
+                }
             }
         }
 
         listTag.add(new StringTag("", "§r§8" + mapping.getJavaIdentifier()));
         if (nbt != null) {
-            listTag.add(new StringTag("", "§r§8" + String.format(MessageTranslator.convertMessage("item.nbt_tags", language), nbt.size())));
+            Component component = Component.text()
+                    .resetStyle()
+                    .color(NamedTextColor.DARK_GRAY)
+                    .append(Component.translatable("item.nbt_tags",
+                            Component.text(nbt.size())))
+                    .build();
+            listTag.add(new StringTag("", MessageTranslator.convertMessage(component, language)));
         }
         compoundTag.put(listTag);
         newNbt.put(compoundTag);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
index 9cd1981c6..249271f99 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
@@ -41,6 +41,10 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement
             builder.put("Base", 15 - bannerColor);
         }
 
+        if (tag == null) {
+            return;
+        }
+
         if (tag.contains("Patterns")) {
             ListTag patterns = tag.get("Patterns");
             if (patterns.equals(BannerTranslator.OMINOUS_BANNER_PATTERN)) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAdventureSettingsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAdventureSettingsTranslator.java
index d4de9e22a..ff094461e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAdventureSettingsTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockAdventureSettingsTranslator.java
@@ -44,15 +44,15 @@ public class BedrockAdventureSettingsTranslator extends PacketTranslator<Adventu
             // We should always be flying in spectator mode
             session.sendAdventureSettings();
             return;
+        } else if (isFlying && session.getPlayerEntity().getFlag(EntityFlag.SWIMMING) && session.getCollisionManager().isPlayerInWater()) {
+            // As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling
+            // If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE
+            session.sendAdventureSettings();
+            return;
         }
 
         session.setFlying(isFlying);
         ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(isFlying);
         session.sendDownstreamPacket(abilitiesPacket);
-
-        if (isFlying && session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
-            // Bedrock can fly and swim at the same time? Make sure that can't happen
-            session.setSwimming(false);
-        }
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java
index f0cf4ff8c..0929e98bd 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandBlockUpdateTranslator.java
@@ -58,7 +58,7 @@ public class BedrockCommandBlockUpdateTranslator extends PacketTranslator<Comman
             session.sendDownstreamPacket(commandBlockPacket);
         } else {
             ServerboundSetCommandMinecartPacket commandMinecartPacket = new ServerboundSetCommandMinecartPacket(
-                    (int) session.getEntityCache().getEntityByGeyserId(packet.getMinecartRuntimeEntityId()).getEntityId(),
+                    session.getEntityCache().getEntityByGeyserId(packet.getMinecartRuntimeEntityId()).getEntityId(),
                     command, outputTracked
             );
             session.sendDownstreamPacket(commandMinecartPacket);
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 d779ab339..65c4ce76b 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
@@ -126,7 +126,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                         if (session.getBlockMappings().isItemFrame(packet.getBlockRuntimeId())) {
                             Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
                             if (itemFrameEntity != null) {
-                                int entityId = (int) itemFrameEntity.getEntityId();
+                                int entityId = itemFrameEntity.getEntityId();
                                 Vector3f vector = packet.getClickPosition();
                                 ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entityId,
                                         InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
@@ -317,7 +317,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
 
                         Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
                         if (itemFrameEntity != null) {
-                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket((int) itemFrameEntity.getEntityId(),
+                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(itemFrameEntity.getEntityId(),
                                     InteractAction.ATTACK, session.isSneaking());
                             session.sendDownstreamPacket(attackPacket);
                             break;
@@ -359,9 +359,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                             break;
                         }
                         Vector3f vector = packet.getClickPosition().sub(entity.getPosition());
-                        ServerboundInteractPacket interactPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+                        ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),
                                 InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
-                        ServerboundInteractPacket interactAtPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+                        ServerboundInteractPacket interactAtPacket = new ServerboundInteractPacket(entity.getEntityId(),
                                 InteractAction.INTERACT_AT, vector.getX(), vector.getY(), vector.getZ(), Hand.MAIN_HAND, session.isSneaking());
                         session.sendDownstreamPacket(interactPacket);
                         session.sendDownstreamPacket(interactAtPacket);
@@ -372,11 +372,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
                         if (entity.getDefinition() == EntityDefinitions.ENDER_DRAGON) {
                             // Redirects the attack to its body entity, this only happens when
                             // attacking the underbelly of the ender dragon
-                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket((int) entity.getEntityId() + 3,
+                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entity.getEntityId() + 3,
                                     InteractAction.ATTACK, session.isSneaking());
                             session.sendDownstreamPacket(attackPacket);
                         } else {
-                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+                            ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entity.getEntityId(),
                                     InteractAction.ATTACK, session.isSneaking());
                             session.sendDownstreamPacket(attackPacket);
                         }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java
index 7ed6e8866..658cf4d79 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java
@@ -47,7 +47,7 @@ public class BedrockItemFrameDropItemTranslator extends PacketTranslator<ItemFra
     public void translate(GeyserSession session, ItemFrameDropItemPacket packet) {
         Entity entity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
         if (entity != null) {
-            ServerboundInteractPacket interactPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+            ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),
                     InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking());
             session.sendDownstreamPacket(interactPacket);
         }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java
index 6d971daeb..3f0e253c6 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockMoveEntityAbsoluteTranslator.java
@@ -45,7 +45,7 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator<MoveEn
     public void translate(GeyserSession session, MoveEntityAbsolutePacket packet) {
         session.setLastVehicleMoveTimestamp(System.currentTimeMillis());
 
-        Entity ridingEntity = session.getRidingVehicleEntity();
+        Entity ridingEntity = session.getPlayerEntity().getVehicle();
         if (ridingEntity != null && session.getWorldBorder().isPassingIntoBorderBoundaries(packet.getPosition(), false)) {
             Vector3f position = Vector3f.from(ridingEntity.getPosition().getX(), packet.getPosition().getY(),
                     ridingEntity.getPosition().getZ());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java
index 75199ae74..ab7ccf394 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPlayerInputTranslator.java
@@ -54,7 +54,7 @@ public class BedrockPlayerInputTranslator extends PacketTranslator<PlayerInputPa
 
         // Bedrock only sends movement vehicle packets while moving
         // This allows horses to take damage while standing on magma
-        Entity vehicle = session.getRidingVehicleEntity();
+        Entity vehicle = session.getPlayerEntity().getVehicle();
         boolean sendMovement = false;
         if (vehicle instanceof AbstractHorseEntity && !(vehicle instanceof LlamaEntity)) {
             sendMovement = vehicle.isOnGround();
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
index 8494daade..0bffc3aae 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
@@ -77,27 +77,32 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
                 session.sendUpstreamPacket(attributesPacket);
                 break;
             case START_SWIMMING:
-                ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
-                session.sendDownstreamPacket(startSwimPacket);
+                if (!entity.getFlag(EntityFlag.SWIMMING)) {
+                    ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
+                    session.sendDownstreamPacket(startSwimPacket);
 
-                session.setSwimming(true);
+                    session.setSwimming(true);
+                }
                 break;
             case STOP_SWIMMING:
-                ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
-                session.sendDownstreamPacket(stopSwimPacket);
+                // Prevent packet spam when Bedrock players are crawling near the edge of a block
+                if (!session.getCollisionManager().mustPlayerCrawlHere()) {
+                    ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
+                    session.sendDownstreamPacket(stopSwimPacket);
 
-                session.setSwimming(false);
+                    session.setSwimming(false);
+                }
                 break;
             case START_GLIDE:
                 // Otherwise gliding will not work in creative
                 ServerboundPlayerAbilitiesPacket playerAbilitiesPacket = new ServerboundPlayerAbilitiesPacket(false);
                 session.sendDownstreamPacket(playerAbilitiesPacket);
             case STOP_GLIDE:
-                ServerboundPlayerCommandPacket glidePacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_ELYTRA_FLYING);
+                ServerboundPlayerCommandPacket glidePacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_ELYTRA_FLYING);
                 session.sendDownstreamPacket(glidePacket);
                 break;
             case START_SNEAK:
-                ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SNEAKING);
+                ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
                 session.sendDownstreamPacket(startSneakPacket);
 
                 // Toggle the shield, if relevant
@@ -120,7 +125,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
                 session.setSneaking(true);
                 break;
             case STOP_SNEAK:
-                ServerboundPlayerCommandPacket stopSneakPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SNEAKING);
+                ServerboundPlayerCommandPacket stopSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SNEAKING);
                 session.sendDownstreamPacket(stopSneakPacket);
 
                 // Stop shield, if necessary
@@ -134,13 +139,17 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
                 session.setSneaking(false);
                 break;
             case START_SPRINT:
-                ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
-                session.sendDownstreamPacket(startSprintPacket);
-                session.setSprinting(true);
+                if (!entity.getFlag(EntityFlag.SWIMMING)) {
+                    ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
+                    session.sendDownstreamPacket(startSprintPacket);
+                    session.setSprinting(true);
+                }
                 break;
             case STOP_SPRINT:
-                ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
-                session.sendDownstreamPacket(stopSprintPacket);
+                if (!entity.getFlag(EntityFlag.SWIMMING)) {
+                    ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
+                    session.sendDownstreamPacket(stopSprintPacket);
+                }
                 session.setSprinting(false);
                 break;
             case DROP_ITEM:
@@ -149,7 +158,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
                 session.sendDownstreamPacket(dropItemPacket);
                 break;
             case STOP_SLEEP:
-                ServerboundPlayerCommandPacket stopSleepingPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.LEAVE_BED);
+                ServerboundPlayerCommandPacket stopSleepingPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.LEAVE_BED);
                 session.sendDownstreamPacket(stopSleepingPacket);
                 break;
             case BLOCK_INTERACT:
@@ -215,7 +224,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
                     // Survival also sends START_BREAK, but by attaching our process here adventure mode also works
                     Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, vector);
                     if (itemFrameEntity != null) {
-                        ServerboundInteractPacket interactPacket = new ServerboundInteractPacket((int) itemFrameEntity.getEntityId(),
+                        ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(itemFrameEntity.getEntityId(),
                                 InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking());
                         session.sendDownstreamPacket(interactPacket);
                         break;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java
index a4fe12d4e..82dcc0d25 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockEmoteTranslator.java
@@ -52,7 +52,7 @@ public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
             }
         }
 
-        long javaId = session.getPlayerEntity().getEntityId();
+        int javaId = session.getPlayerEntity().getEntityId();
         for (GeyserSession otherSession : session.getGeyser().getSessionManager().getSessions().values()) {
             if (otherSession != session) {
                 if (otherSession.isClosed()) continue;
@@ -65,7 +65,7 @@ public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
         }
     }
 
-    private void playEmote(GeyserSession otherSession, long javaId, String emoteId) {
+    private void playEmote(GeyserSession otherSession, int javaId, String emoteId) {
         Entity otherEntity = otherSession.getEntityCache().getEntityByJavaId(javaId); // Must be ran on same thread
         if (otherEntity == null) return;
         EmotePacket otherEmotePacket = new EmotePacket();
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
index 26a25725e..2d32156c0 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockInteractTranslator.java
@@ -62,19 +62,18 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
                 if (session.getPlayerInventory().getItemInHand().getJavaId() == session.getItemMappings().getStoredItems().shield().getJavaId()) {
                     break;
                 }
-                ServerboundInteractPacket interactPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+                ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),
                         InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
                 session.sendDownstreamPacket(interactPacket);
                 break;
             case DAMAGE:
-                ServerboundInteractPacket attackPacket = new ServerboundInteractPacket((int) entity.getEntityId(),
+                ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entity.getEntityId(),
                         InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking());
                 session.sendDownstreamPacket(attackPacket);
                 break;
             case LEAVE_VEHICLE:
-                ServerboundPlayerCommandPacket sneakPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SNEAKING);
+                ServerboundPlayerCommandPacket sneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING);
                 session.sendDownstreamPacket(sneakPacket);
-                session.setRidingVehicleEntity(null);
                 break;
             case MOUSEOVER:
                 // Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc
@@ -97,11 +96,11 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
                 break;
             case OPEN_INVENTORY:
                 if (session.getOpenInventory() == null) {
-                    Entity ridingEntity = session.getRidingVehicleEntity();
+                    Entity ridingEntity = session.getPlayerEntity().getVehicle();
                     if (ridingEntity instanceof AbstractHorseEntity) {
                         if (ridingEntity.getFlag(EntityFlag.TAMED)) {
                             // We should request to open the horse inventory instead
-                            ServerboundPlayerCommandPacket openHorseWindowPacket = new ServerboundPlayerCommandPacket((int) session.getPlayerEntity().getEntityId(), PlayerState.OPEN_HORSE_INVENTORY);
+                            ServerboundPlayerCommandPacket openHorseWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_HORSE_INVENTORY);
                             session.sendDownstreamPacket(openHorseWindowPacket);
                         }
                     } else {
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 1555722d6..7c170fdbc 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
@@ -67,7 +67,8 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
         // Send book update before the player moves
         session.getBookEditCache().checkForSend();
 
-        if (!session.getTeleportMap().isEmpty()) {
+        // Ignore movement packets until Bedrock's position matches the teleported position
+        if (session.getUnconfirmedTeleport() != null) {
             session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityDefinitions.PLAYER.offset(), 0));
             return;
         }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java
index 79911b5e7..89126b258 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockRiderJumpTranslator.java
@@ -38,9 +38,9 @@ import org.geysermc.geyser.translator.protocol.Translator;
 public class BedrockRiderJumpTranslator extends PacketTranslator<RiderJumpPacket> {
     @Override
     public void translate(GeyserSession session, RiderJumpPacket packet) {
-        Entity vehicle = session.getRidingVehicleEntity();
+        Entity vehicle = session.getPlayerEntity().getVehicle();
         if (vehicle instanceof AbstractHorseEntity) {
-            ServerboundPlayerCommandPacket playerCommandPacket = new ServerboundPlayerCommandPacket((int) vehicle.getEntityId(),  PlayerState.START_HORSE_JUMP, packet.getJumpStrength());
+            ServerboundPlayerCommandPacket playerCommandPacket = new ServerboundPlayerCommandPacket(vehicle.getEntityId(), PlayerState.START_HORSE_JUMP, packet.getJumpStrength());
             session.sendDownstreamPacket(playerCommandPacket);
         }
     }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java
index d7fc79f1e..fb4e2653d 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAnimateTranslator.java
@@ -41,12 +41,7 @@ public class JavaAnimateTranslator extends PacketTranslator<ClientboundAnimatePa
 
     @Override
     public void translate(GeyserSession session, ClientboundAnimatePacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null)
             return;
 
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 eb54ad942..1fc7af784 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
@@ -34,6 +34,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
 import com.nukkitx.protocol.bedrock.packet.*;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.EntityDefinitions;
+import org.geysermc.geyser.entity.type.EvokerFangsEntity;
 import org.geysermc.geyser.entity.type.FishingHookEntity;
 import org.geysermc.geyser.entity.type.LivingEntity;
 import org.geysermc.geyser.session.GeyserSession;
@@ -47,12 +48,7 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
 
     @Override
     public void translate(GeyserSession session, ClientboundEntityEventPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null)
             return;
 
@@ -124,8 +120,8 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
                 // Player is pulled from a fishing rod
                 // The physics of this are clientside on Java
                 FishingHookEntity fishingHook = (FishingHookEntity) entity;
-                if (fishingHook.isOwnerSessionPlayer()) {
-                    Entity hookOwner = session.getEntityCache().getEntityByGeyserId(fishingHook.getBedrockTargetId());
+                if (fishingHook.getBedrockTargetId() == session.getPlayerEntity().getGeyserId()) {
+                    Entity hookOwner = session.getEntityCache().getEntityByGeyserId(fishingHook.getBedrockOwnerId());
                     if (hookOwner != null) {
                         // https://minecraft.gamepedia.com/Fishing_Rod#Hooking_mobs_and_other_entities
                         SetEntityMotionPacket motionPacket = new SetEntityMotionPacket();
@@ -183,8 +179,11 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
                 entityEventPacket.setType(EntityEventType.GOLEM_FLOWER_WITHDRAW);
                 break;
             case IRON_GOLEM_ATTACK:
-                if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM) {
+                if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM || entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
                     entityEventPacket.setType(EntityEventType.ATTACK_START);
+                    if (entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
+                        ((EvokerFangsEntity) entity).setAttackStarted();
+                    }
                 }
                 break;
             case RABBIT_JUMP_OR_MINECART_SPAWNER_DELAY_RESET:
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java
index 4f15b0717..0b54ad3b3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosRotTranslator.java
@@ -37,9 +37,6 @@ public class JavaMoveEntityPosRotTranslator extends PacketTranslator<Clientbound
     @Override
     public void translate(GeyserSession session, ClientboundMoveEntityPosRotPacket packet) {
         Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        }
         if (entity == null) return;
 
         entity.updatePositionAndRotation(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), packet.getYaw(), packet.getPitch(), packet.isOnGround());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java
index aeb080465..16de5204f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityPosTranslator.java
@@ -36,12 +36,7 @@ public class JavaMoveEntityPosTranslator extends PacketTranslator<ClientboundMov
 
     @Override
     public void translate(GeyserSession session, ClientboundMoveEntityPosPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null) return;
 
         entity.moveRelative(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), entity.getYaw(), entity.getPitch(), entity.getHeadYaw(), packet.isOnGround());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java
index b2b59480b..da6fae35f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveEntityRotTranslator.java
@@ -37,9 +37,6 @@ public class JavaMoveEntityRotTranslator extends PacketTranslator<ClientboundMov
     @Override
     public void translate(GeyserSession session, ClientboundMoveEntityRotPacket packet) {
         Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        }
         if (entity == null) return;
 
         entity.updateRotation(packet.getYaw(), packet.getPitch(), packet.isOnGround());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java
index 90e121250..33122e34d 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaMoveVehicleTranslator.java
@@ -37,7 +37,7 @@ public class JavaMoveVehicleTranslator extends PacketTranslator<ClientboundMoveV
 
     @Override
     public void translate(GeyserSession session, ClientboundMoveVehiclePacket packet) {
-        Entity entity = session.getRidingVehicleEntity();
+        Entity entity = session.getPlayerEntity().getVehicle();
         if (entity == null) return;
 
         entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), false, true);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java
index bc78bb33e..6749cf1b3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRemoveMobEffectTranslator.java
@@ -38,12 +38,9 @@ public class JavaRemoveMobEffectTranslator extends PacketTranslator<ClientboundR
 
     @Override
     public void translate(GeyserSession session, ClientboundRemoveMobEffectPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
+        Entity entity  = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
+        if (entity == session.getPlayerEntity()) {
             session.getEffectCache().removeEffect(packet.getEffect());
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         }
         if (entity == null)
             return;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java
index edcad7af6..4293dd0cc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaRotateHeadTranslator.java
@@ -36,13 +36,7 @@ public class JavaRotateHeadTranslator extends PacketTranslator<ClientboundRotate
 
     @Override
     public void translate(GeyserSession session, ClientboundRotateHeadPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null) return;
 
         entity.updateHeadLookRotation(packet.getHeadYaw());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java
index 440fcaea1..8a568ba9f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityDataTranslator.java
@@ -40,12 +40,7 @@ public class JavaSetEntityDataTranslator extends PacketTranslator<ClientboundSet
     @SuppressWarnings({"rawtypes", "unchecked"})
     @Override
     public void translate(GeyserSession session, ClientboundSetEntityDataPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null) return;
 
         EntityDefinition<?> definition = entity.getDefinition();
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java
index 88f1c8ae1..deed9e65e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityLinkTranslator.java
@@ -43,33 +43,23 @@ public class JavaSetEntityLinkTranslator extends PacketTranslator<ClientboundSet
 
     @Override
     public void translate(GeyserSession session, ClientboundSetEntityLinkPacket packet) {
-        Entity holderId;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            holderId = session.getPlayerEntity();
-        } else {
-            holderId = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity holderId = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (!(holderId instanceof MobEntity mobEntity)) {
             return;
         }
 
-        Entity attachedToId;
-        if (packet.getAttachedToId() == session.getPlayerEntity().getEntityId()) {
-            attachedToId = session.getPlayerEntity();
-        } else {
-            attachedToId = session.getEntityCache().getEntityByJavaId(packet.getAttachedToId());
-            if ((attachedToId == null || packet.getAttachedToId() == 0)) {
-                // Is not being leashed
-                mobEntity.setFlag(EntityFlag.LEASHED, false);
-                mobEntity.setLeashHolderBedrockId(-1L);
-                mobEntity.updateBedrockMetadata();
-                EntityEventPacket eventPacket = new EntityEventPacket();
-                eventPacket.setRuntimeEntityId(holderId.getGeyserId());
-                eventPacket.setType(EntityEventType.REMOVE_LEASH);
-                eventPacket.setData(0);
-                session.sendUpstreamPacket(eventPacket);
-                return;
-            }
+        Entity attachedToId = session.getEntityCache().getEntityByJavaId(packet.getAttachedToId());
+        if (attachedToId == null || packet.getAttachedToId() == 0) {
+            // Is not being leashed
+            mobEntity.setFlag(EntityFlag.LEASHED, false);
+            mobEntity.setLeashHolderBedrockId(-1L);
+            mobEntity.updateBedrockMetadata();
+            EntityEventPacket eventPacket = new EntityEventPacket();
+            eventPacket.setRuntimeEntityId(holderId.getGeyserId());
+            eventPacket.setType(EntityEventType.REMOVE_LEASH);
+            eventPacket.setData(0);
+            session.sendUpstreamPacket(eventPacket);
+            return;
         }
 
         mobEntity.setFlag(EntityFlag.LEASHED, true);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java
index 5febe4813..83eacfa37 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEntityMotionTranslator.java
@@ -41,17 +41,12 @@ public class JavaSetEntityMotionTranslator extends PacketTranslator<ClientboundS
 
     @Override
     public void translate(GeyserSession session, ClientboundSetEntityMotionPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null) return;
 
         entity.setMotion(Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()));
 
-        if (entity == session.getRidingVehicleEntity() && entity instanceof AbstractHorseEntity) {
+        if (entity == session.getPlayerEntity().getVehicle() && entity instanceof AbstractHorseEntity) {
             // Horses for some reason teleport back when a SetEntityMotionPacket is sent while
             // a player is riding on them. Java clients seem to ignore it anyways.
             return;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
index ebfe40832..8d85007c3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetEquipmentTranslator.java
@@ -44,13 +44,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
 
     @Override
     public void translate(GeyserSession session, ClientboundSetEquipmentPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null)
             return;
 
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java
index f4a6f94ed..3d51c9401 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java
@@ -29,100 +29,73 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.Client
 import com.nukkitx.protocol.bedrock.data.entity.EntityData;
 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.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.EntityDefinitions;
+import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
 import org.geysermc.geyser.util.EntityUtils;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 
 @Translator(packet = ClientboundSetPassengersPacket.class)
 public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSetPassengersPacket> {
 
     @Override
     public void translate(GeyserSession session, ClientboundSetPassengersPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
-
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (entity == null) return;
 
-        LongOpenHashSet passengers = entity.getPassengers().clone();
-        boolean rider = true;
-        for (long passengerId : packet.getPassengerIds()) {
+        // Handle new/existing passengers
+        List<Entity> newPassengers = new ArrayList<>();
+        for (int passengerId : packet.getPassengerIds()) {
             Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId);
-            if (passengerId == session.getPlayerEntity().getEntityId()) {
-                passenger = session.getPlayerEntity();
-                session.setRidingVehicleEntity(entity);
+            if (passenger == session.getPlayerEntity()) {
+                session.getPlayerEntity().setVehicle(entity);
                 // We need to confirm teleports before entering a vehicle, or else we will likely exit right out
                 session.confirmTeleport(passenger.getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0).toDouble());
             }
-            // Passenger hasn't loaded in (likely since we're waiting for a skin response)
-            // and entity link needs to be set later
-            if (passenger == null && passengerId != 0) {
-                session.getEntityCache().addCachedPlayerEntityLink(passengerId, packet.getEntityId());
-            }
             if (passenger == null) {
+                // Can occur if the passenger is outside the client's tracking range
+                // In this case, another SetPassengers packet will be sent when the passenger is spawned.
                 continue;
             }
 
+            boolean rider = packet.getPassengerIds()[0] == passengerId;
             EntityLinkData.Type type = rider ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER;
             SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
-            linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false));
+            linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false, false));
             session.sendUpstreamPacket(linkPacket);
-            passengers.add(passengerId);
-
-            // Head rotation on boats
-            if (entity.getDefinition() == EntityDefinitions.BOAT) {
-                passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 1f);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, -90f);
-            } else {
-                passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
-            }
-
-            passenger.updateBedrockMetadata();
-            rider = false;
-        }
-
-        entity.setPassengers(passengers);
-
-        for (long passengerId : entity.getPassengers()) {
-            Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId);
-            if (passengerId == session.getPlayerEntity().getEntityId()) {
-                passenger = session.getPlayerEntity();
-            }
-            if (passenger == null) {
-                continue;
-            }
-            if (Arrays.stream(packet.getPassengerIds()).noneMatch(id -> id == passengerId)) {
-                SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
-                linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false));
-                session.sendUpstreamPacket(linkPacket);
-                passengers.remove(passenger.getEntityId());
-                passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
-                passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
-
-                EntityUtils.updateMountOffset(passenger, entity, false, false, (packet.getPassengerIds().length > 1));
-            } else {
-                EntityUtils.updateMountOffset(passenger, entity, (packet.getPassengerIds()[0] == passengerId), true, (packet.getPassengerIds().length > 1));
-            }
+            newPassengers.add(passenger);
 
+            passenger.setVehicle(entity);
+            EntityUtils.updateRiderRotationLock(passenger, entity, true);
+            EntityUtils.updateMountOffset(passenger, entity, rider, true, (packet.getPassengerIds().length > 1));
             // Force an update to the passenger metadata
             passenger.updateBedrockMetadata();
         }
 
+        // Handle passengers that were removed
+        for (Entity passenger : entity.getPassengers()) {
+            if (passenger == null) {
+                continue;
+            }
+            if (!newPassengers.contains(passenger)) {
+                SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
+                linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false, false));
+                session.sendUpstreamPacket(linkPacket);
+
+                passenger.setVehicle(null);
+                EntityUtils.updateRiderRotationLock(passenger, entity, false);
+                EntityUtils.updateMountOffset(passenger, entity, false, false, (packet.getPassengerIds().length > 1));
+                // Force an update to the passenger metadata
+                passenger.updateBedrockMetadata();
+            }
+        }
+
+        entity.setPassengers(newPassengers);
+
         switch (entity.getDefinition().entityType()) {
             case HORSE, SKELETON_HORSE, DONKEY, MULE, RAVAGER -> {
                 entity.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 181.0f);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java
index 75d7bc976..dbf335ceb 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTakeItemEntityTranslator.java
@@ -49,12 +49,7 @@ public class JavaTakeItemEntityTranslator extends PacketTranslator<ClientboundTa
         Entity collectedEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectedEntityId());
         if (collectedEntity == null) return;
         // Collector is the entity 'picking up' the item
-        Entity collectorEntity;
-        if (packet.getCollectorEntityId() == session.getPlayerEntity().getEntityId()) {
-            collectorEntity = session.getPlayerEntity();
-        } else {
-            collectorEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectorEntityId());
-        }
+        Entity collectorEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectorEntityId());
         if (collectorEntity == null) return;
         if (collectedEntity instanceof ExpOrbEntity) {
             // Player just picked up an experience orb
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java
index cbd994d79..d6698c46b 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaTeleportEntityTranslator.java
@@ -38,9 +38,6 @@ public class JavaTeleportEntityTranslator extends PacketTranslator<ClientboundTe
     @Override
     public void translate(GeyserSession session, ClientboundTeleportEntityPacket packet) {
         Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        }
         if (entity == null) return;
 
         entity.teleport(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), packet.isOnGround());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java
index c3a4e4ac4..501766735 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateAttributesTranslator.java
@@ -37,12 +37,7 @@ public class JavaUpdateAttributesTranslator extends PacketTranslator<Clientbound
 
     @Override
     public void translate(GeyserSession session, ClientboundUpdateAttributesPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
-        }
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         if (!(entity instanceof LivingEntity livingEntity)) return;
 
         livingEntity.updateBedrockAttributes(session, packet.getAttributes());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java
index 2d4161739..8e4cfa968 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaUpdateMobEffectTranslator.java
@@ -38,12 +38,9 @@ public class JavaUpdateMobEffectTranslator extends PacketTranslator<ClientboundU
 
     @Override
     public void translate(GeyserSession session, ClientboundUpdateMobEffectPacket packet) {
-        Entity entity;
-        if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
-            entity = session.getPlayerEntity();
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
+        if (entity == session.getPlayerEntity()) {
             session.getEffectCache().setEffect(packet.getEffect(), packet.getAmplifier());
-        } else {
-            entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
         }
         if (entity == null)
             return;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
index 3e94321f9..f5b2d44d5 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
@@ -28,22 +28,22 @@ package org.geysermc.geyser.translator.protocol.java.entity.player;
 import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement;
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket;
 import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket;
+import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
 import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.data.entity.EntityData;
 import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
 import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
 import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
 import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
-import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.EntityDefinitions;
-import org.geysermc.geyser.entity.type.player.PlayerEntity;
+import org.geysermc.geyser.entity.type.Entity;
+import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.session.cache.TeleportCache;
+import org.geysermc.geyser.text.GeyserLocale;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
 import org.geysermc.geyser.util.ChunkUtils;
 import org.geysermc.geyser.util.EntityUtils;
-import org.geysermc.geyser.text.GeyserLocale;
 
 @Translator(packet = ClientboundPlayerPositionPacket.class)
 public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPlayerPositionPacket> {
@@ -53,9 +53,10 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
         if (!session.isLoggedIn())
             return;
 
-        PlayerEntity entity = session.getPlayerEntity();
+        SessionPlayerEntity entity = session.getPlayerEntity();
 
         if (!session.isSpawned()) {
+            // The server sends an absolute teleport everytime the player is respawned
             Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
             entity.setPosition(pos);
             entity.setYaw(packet.getYaw());
@@ -78,9 +79,10 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
 
             session.sendUpstreamPacket(movePlayerPacket);
             session.setSpawned(true);
+            // Make sure the player moves away from (0, 32767, 0) before accepting movement packets
+            session.setUnconfirmedTeleport(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getPitch(), packet.getYaw(), packet.getTeleportId()));
 
-            ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(packet.getTeleportId());
-            session.sendDownstreamPacket(teleportConfirmPacket);
+            acceptTeleport(session, packet.getX(), packet.getY(), packet.getZ(), packet.getYaw(), packet.getPitch(), packet.getTeleportId());
 
             ChunkUtils.updateChunkPosition(session, pos.toInt());
 
@@ -88,22 +90,19 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
             return;
         }
 
-        session.setSpawned(true);
+        Entity vehicle = session.getPlayerEntity().getVehicle();
+        if (packet.isDismountVehicle() && vehicle != null) {
 
-        if (packet.isDismountVehicle() && session.getRidingVehicleEntity() != null) {
-            Entity vehicle = session.getRidingVehicleEntity();
             SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
             linkPacket.setEntityLink(new EntityLinkData(vehicle.getGeyserId(), entity.getGeyserId(), EntityLinkData.Type.REMOVE, false, false));
             session.sendUpstreamPacket(linkPacket);
-            vehicle.getPassengers().remove(entity.getEntityId());
-            entity.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
-            entity.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
-            entity.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
-            entity.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
-            session.setRidingVehicleEntity(null);
-            entity.updateBedrockMetadata();
 
-            EntityUtils.updateMountOffset(entity, vehicle, false, false, entity.getPassengers().size() > 1);
+            vehicle.getPassengers().remove(entity);
+            session.getPlayerEntity().setVehicle(null);
+
+            EntityUtils.updateRiderRotationLock(entity, null, false);
+            EntityUtils.updateMountOffset(entity, null, false, false, entity.getPassengers().size() > 1);
+            entity.updateBedrockMetadata();
         }
 
         // If coordinates are relative, then add to the existing coordinate
@@ -119,9 +118,9 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
         float newYaw = packet.getYaw() +
                 (packet.getRelative().contains(PositionElement.YAW) ? entity.getBedrockRotation().getY() : 0);
 
-        session.getGeyser().getLogger().debug("Teleport from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
+        int id = packet.getTeleportId();
 
-        session.addTeleport(new TeleportCache(newX, newY, newZ, newPitch, newYaw, packet.getTeleportId()));
+        session.getGeyser().getLogger().debug("Teleport (" + id + ") from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
 
         Vector3f lastPlayerPosition = entity.getPosition().down(EntityDefinitions.PLAYER.offset());
         float lastPlayerPitch = entity.getBedrockRotation().getX();
@@ -131,9 +130,22 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
         session.getGeyser().getLogger().debug("to " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
 
         // Bedrock ignores teleports that are extremely close to the player's original position and orientation,
-        // so check if we can immediately confirm the teleport
+        // so check if we need to cache the teleport
         if (lastPlayerPosition.distanceSquared(teleportDestination) < 0.001 && Math.abs(newPitch - lastPlayerPitch) < 5) {
-            session.confirmTeleport(lastPlayerPosition.toDouble());
+            session.setUnconfirmedTeleport(null);
+        } else {
+            session.setUnconfirmedTeleport(new TeleportCache(newX, newY, newZ, newPitch, newYaw, id));
         }
+
+        acceptTeleport(session, newX, newY, newZ, newYaw, newPitch, id);
+    }
+
+    private void acceptTeleport(GeyserSession session, double x, double y, double z, float yaw, float pitch, int id) {
+        // Confirm the teleport when we receive it to match Java edition
+        ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(id);
+        session.sendDownstreamPacket(teleportConfirmPacket);
+        // Servers (especially ones like Hypixel) expect exact coordinates given back to them.
+        ServerboundMovePlayerPosRotPacket positionPacket = new ServerboundMovePlayerPosRotPacket(false, x, y, z, yaw, pitch);
+        session.sendDownstreamPacket(positionPacket);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java
index b80b59ff4..89f65d38e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddEntityTranslator.java
@@ -31,18 +31,17 @@ import com.github.steveice10.mc.protocol.data.game.entity.object.ProjectileData;
 import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket;
 import com.nukkitx.math.vector.Vector3f;
-import org.geysermc.geyser.entity.*;
-import org.geysermc.geyser.entity.factory.BaseEntityFactory;
+import org.geysermc.geyser.entity.EntityDefinition;
 import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.type.FallingBlockEntity;
 import org.geysermc.geyser.entity.type.FishingHookEntity;
 import org.geysermc.geyser.entity.type.ItemFrameEntity;
 import org.geysermc.geyser.entity.type.player.PlayerEntity;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.GeyserLocale;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.text.GeyserLocale;
 
 @Translator(packet = ClientboundAddEntityPacket.class)
 public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEntityPacket> {
@@ -71,12 +70,7 @@ public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEnti
         } else if (packet.getType() == EntityType.FISHING_BOBBER) {
             // Fishing bobbers need the owner for the line
             int ownerEntityId = ((ProjectileData) packet.getData()).getOwnerId();
-            Entity owner;
-            if (session.getPlayerEntity().getEntityId() == ownerEntityId) {
-                owner = session.getPlayerEntity();
-            } else {
-                owner = session.getEntityCache().getEntityByJavaId(ownerEntityId);
-            }
+            Entity owner = session.getEntityCache().getEntityByJavaId(ownerEntityId);
             // Java clients only spawn fishing hooks with a player as its owner
             if (owner instanceof PlayerEntity) {
                 entity = new FishingHookEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),
@@ -85,7 +79,7 @@ public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEnti
                 return;
             }
         } else {
-            entity = ((BaseEntityFactory<?>) definition.factory()).create(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
+            entity = definition.factory().create(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
                     packet.getUuid(), definition, position, motion, yaw, pitch, 0f);
         }
         session.getEntityCache().spawnEntity(entity);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddMobTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddMobTranslator.java
index e6b82f365..25f4489d7 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddMobTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/spawn/JavaAddMobTranslator.java
@@ -27,14 +27,13 @@ package org.geysermc.geyser.translator.protocol.java.entity.spawn;
 
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddMobPacket;
 import com.nukkitx.math.vector.Vector3f;
-import org.geysermc.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.entity.factory.BaseEntityFactory;
+import org.geysermc.geyser.entity.type.Entity;
+import org.geysermc.geyser.registry.Registries;
 import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.GeyserLocale;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.text.GeyserLocale;
 
 @Translator(packet = ClientboundAddMobPacket.class)
 public class JavaAddMobTranslator extends PacketTranslator<ClientboundAddMobPacket> {
@@ -50,7 +49,7 @@ public class JavaAddMobTranslator extends PacketTranslator<ClientboundAddMobPack
             return;
         }
 
-        Entity entity = ((BaseEntityFactory<?>) definition.factory()).create(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
+        Entity entity = definition.factory().create(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
                 packet.getUuid(), definition, position, motion, packet.getYaw(), packet.getPitch(), packet.getHeadYaw()
         );
         session.getEntityCache().spawnEntity(entity);
diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java
index cb80e209b..9dcb9f303 100644
--- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java
@@ -27,7 +27,6 @@ package org.geysermc.geyser.util;
 
 import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
 import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.github.steveice10.opennbt.tag.builtin.DoubleTag;
 import com.github.steveice10.opennbt.tag.builtin.IntTag;
 import com.nukkitx.math.vector.Vector2i;
 import com.nukkitx.math.vector.Vector3i;
@@ -40,14 +39,14 @@ import it.unimi.dsi.fastutil.ints.IntLists;
 import lombok.experimental.UtilityClass;
 import org.geysermc.geyser.entity.type.ItemFrameEntity;
 import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
-import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.text.GeyserLocale;
-import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
 import org.geysermc.geyser.level.chunk.BlockStorage;
 import org.geysermc.geyser.level.chunk.GeyserChunkSection;
 import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray;
 import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.GeyserLocale;
+import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
 
 import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID;
 
@@ -264,7 +263,10 @@ public class ChunkUtils {
         session.getChunkCache().setHeightY(maxY);
 
         // Load world coordinate scale for the world border
-        double coordinateScale = ((DoubleTag) dimensionTag.get("coordinate_scale")).getValue();
+        double coordinateScale = ((Number) dimensionTag.get("coordinate_scale").getValue()).doubleValue();
         session.getWorldBorder().setWorldCoordinateScale(coordinateScale);
+
+        // Set if piglins/hoglins should shake
+        session.setDimensionPiglinSafe(((Number) dimensionTag.get("piglin_safe").getValue()).byteValue() != (byte) 0);
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
index 4bcbf6e68..7eec2490c 100644
--- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.util;
 import com.github.steveice10.mc.protocol.data.game.entity.Effect;
 import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
 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.geyser.entity.type.Entity;
 import org.geysermc.geyser.entity.EntityDefinitions;
@@ -74,7 +75,7 @@ public final class EntityUtils {
         switch (mount.getDefinition().entityType()) {
             case CHICKEN, SPIDER -> mountedHeightOffset = height * 0.5f;
             case DONKEY, MULE -> mountedHeightOffset -= 0.25f;
-            case LLAMA -> mountedHeightOffset = height * 0.67f;
+            case TRADER_LLAMA, LLAMA -> mountedHeightOffset = height * 0.6f;
             case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
                     COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0;
             case BOAT -> mountedHeightOffset = -0.1f;
@@ -144,20 +145,22 @@ public final class EntityUtils {
             float yOffset = mountedHeightOffset + heightOffset;
             float zOffset = 0;
             switch (mount.getDefinition().entityType()) {
-                case BOAT:
+                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;
+                }
+                case CHICKEN -> zOffset = -0.1f;
+                case TRADER_LLAMA, LLAMA -> zOffset = -0.3f;
+            }
+            if (passenger.getDefinition().entityType() == EntityType.SHULKER) {
+                switch (mount.getDefinition().entityType()) {
+                    case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
+                            COMMAND_BLOCK_MINECART, BOAT -> yOffset = 0.1875f;
+                }
             }
             /*
              * Bedrock Differences
@@ -165,8 +168,10 @@ public final class EntityUtils {
              * Horses are tinier
              * Players, Minecarts, and Boats have different origins
              */
-            if (passenger.getDefinition().entityType() == EntityType.PLAYER && mount.getDefinition().entityType() != EntityType.PLAYER) {
-                yOffset += EntityDefinitions.PLAYER.offset();
+            if (passenger.getDefinition().entityType() == EntityType.PLAYER) {
+                if (mount.getDefinition().entityType() != EntityType.PLAYER && mount.getDefinition().entityType() != EntityType.AREA_EFFECT_CLOUD) {
+                    yOffset += EntityDefinitions.PLAYER.offset();
+                }
             }
             switch (mount.getDefinition().entityType()) {
                 case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
@@ -175,7 +180,21 @@ public final class EntityUtils {
             Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset);
             passenger.setRiderSeatPosition(offset);
         }
-        passenger.updateBedrockMetadata();
+    }
+
+    public static void updateRiderRotationLock(Entity passenger, Entity mount, boolean isRiding) {
+        if (isRiding && mount.getDefinition() == EntityDefinitions.BOAT) {
+            // Head rotation is locked while riding in a boat
+            passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 1f);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, -90f);
+        } else {
+            passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
+            passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
+        }
     }
 
     private EntityUtils() {
diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings
index 82ad7ba27..ea5950882 160000
--- a/core/src/main/resources/mappings
+++ b/core/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit 82ad7ba279c68eb11a0b1a969c9efb3228c59227
+Subproject commit ea5950882edebc1a0e5cee0626b958f233dfe434