Paper/patches/server/0523-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch

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 27fc9ec7183b100dcfc755d41b3348ccc04c705b..a6a14c6d3eb6d77997e1763e2dd451e0718511ea 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -681,7 +681,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;
@@ -1548,7 +1548,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.forceCheckHighPriority(); // Paper
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 e1b6a390105232500d7146cc456bf30912934904..993a7000595181a83754f192a53ec2bfe1a2eddc 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -152,6 +152,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
// 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;
}
@@ -1545,6 +1546,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
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 b9e738542692aba7b78fc514ae8e3248df9998ea..c601b8b12756682a4cb300be8ebed4319902c5b5 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -170,6 +170,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 17ad49994499982a08c1e8a4b4635647d669986a..187504b19f0194c700b5e498be191cf58b8d34ad 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -567,7 +567,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());