From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 25 Aug 2020 20:45:36 -0400
Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported

Uses correct setPositionRotation for Entity teleporting instead of setLocation
as this is how Vanilla teleports entities.

Cancel any pending motion when teleported.

diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 6aeea48d4cf4732f6a5a5dba12af873c2aee493b..fa0256a99c833e6035b8d3e873a93af2b674ef52 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -54,6 +54,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
 
     // CraftBukkit start
     private static final int CURRENT_LEVEL = 2;
+    boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation
     static boolean isLevelAtLeast(NBTTagCompound tag, int level) {
         return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
     }
@@ -1317,6 +1318,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
     }
 
     public void setPositionRotation(double d0, double d1, double d2, float f, float f1) {
+        // Paper - cancel entity velocity if teleported
+        if (!preserveMotion) {
+            this.mot = Vec3D.ORIGIN;
+        } else {
+            this.preserveMotion = false;
+        }
+        // Paper end
         this.g(d0, d1, d2);
         this.yaw = f;
         this.pitch = f1;
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 6cb6a6d2cdf25c7db0e3d2c79af2c1002a04d14b..d622abf1013d500532cc6072e5cbb12248e983c2 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -544,7 +544,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
     public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) {
         PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer());
         if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit
-            this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch);
+            this.player.setPositionRotation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); // Paper - use proper setPositionRotation for teleportation
             this.o = this.teleportPos.x;
             this.p = this.teleportPos.y;
             this.q = this.teleportPos.z;
@@ -1378,7 +1378,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
         // CraftBukkit end
 
         this.A = this.e;
-        this.player.setLocation(d0, d1, d2, f, f1);
+        this.player.setPositionRotation(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation
         this.player.forceCheckHighPriority(); // Paper
         this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait));
     }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 2ca79b3e9b3418a2a8dd8ee9e3fb9d41aec1e43c..f1243b308e44d7c08e007d8ce080c2fc6248753c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -549,7 +549,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
         }
 
         // entity.setLocation() throws no event, and so cannot be cancelled
-        entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+        entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting
         // SPIGOT-619: Force sync head rotation also
         entity.setHeadRotation(location.getYaw());
         ((net.minecraft.server.WorldServer) entity.world).chunkCheck(entity); // Spigot - register to new chunk
