Paper/patches/server/0503-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch
2022-02-28 22:52:35 -07:00

84 lines
5.3 KiB
Diff

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/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index b0b715660d17751d4bc6c8d23dc288ca246608ec..758c10215a14f51c95657fe9b392e3f1ed37ec3c 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -685,7 +685,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit
- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
+ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); // Paper - use proper setPositionRotation for teleportation
this.lastGoodX = this.awaitingPositionFromClient.x;
this.lastGoodY = this.awaitingPositionFromClient.y;
this.lastGoodZ = this.awaitingPositionFromClient.z;
@@ -1569,7 +1569,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit end
this.awaitingTeleportTime = this.tickCount;
- this.player.absMoveTo(d0, d1, d2, f, f1);
+ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation
this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag));
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index e18b2855791002a20f5afaa87cbfb36023ba4b7f..b3d636566d818aa3113501bf1620af29c62602fd 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -154,6 +154,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation
static boolean isLevelAtLeast(CompoundTag tag, int level) {
return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
}
@@ -1567,6 +1568,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
}
public void moveTo(double x, double y, double z, float yaw, float pitch) {
+ // Paper - cancel entity velocity if teleported
+ if (!preserveMotion) {
+ this.deltaMovement = Vec3.ZERO;
+ } else {
+ this.preserveMotion = false;
+ }
+ // Paper end
this.setPosRaw(x, y, z);
this.setYRot(yaw);
this.setXRot(pitch);
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index 70e1f9bd9e4711aaf45ff8b7214726de646997ab..4bfebbb2e87464cd47a38a5da6275b2c662fa052 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -161,6 +161,7 @@ public abstract class BaseSpawner {
return;
}
+ entity.preserveMotion = true; // Paper - preserve entity motion from tag
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 1fb0d345b0b22d40d9313f35c792c646533da008..27c48e853ee93ab8eeb27560666fafc1057585be 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -579,7 +579,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// entity.setLocation() throws no event, and so cannot be cancelled
- this.entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ entity.moveTo(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
this.entity.setYHeadRot(location.getYaw());