From 900e3eacd263000429536d32cc8e1cb2dd393c82 Mon Sep 17 00:00:00 2001 From: Sky Date: Thu, 13 Aug 2026 17:04:47 +0300 Subject: [PATCH 1/4] Add PlayerPrepareTeleportEvent --- .../player/PlayerPrepareTeleportEvent.java | 81 +++++++++++++++++++ .../craftbukkit/entity/CraftPlayer.java | 7 ++ 2 files changed, 88 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java new file mode 100644 index 000000000000..77adcc73882b --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java @@ -0,0 +1,81 @@ +package io.papermc.paper.event.player; + +import io.papermc.paper.entity.TeleportFlag; +import java.util.Set; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Unmodifiable; +import org.jspecify.annotations.NullMarked; + +/** + * Event that is fired before attempting to teleport a player (Allows for pre-teleport handling, such as dismounting passengers if teleporting cross-worlds etc.) + *

+ * After the handling of this event, the player will attempt to teleport to the given location. + */ +@NullMarked +public class PlayerPrepareTeleportEvent extends PlayerEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Location to; + private final PlayerTeleportEvent.TeleportCause cause; + private final Set teleportFlags; + + @ApiStatus.Internal + public PlayerPrepareTeleportEvent(final Player player, Location to, PlayerTeleportEvent.TeleportCause cause, Set teleportFlags) { + super(player); + this.to = to; + this.cause = cause; + this.teleportFlags = teleportFlags; + } + + /** + * Gets the location this player is teleporting to + * + * @return A copy of the Location the player is teleporting to + */ + public Location getTo() { + return this.to.clone(); + } + + /** + * Gets the location this player is teleporting from + * + * @return A copy of the Location the player is moving from + */ + public Location getFrom() { + return this.getPlayer().getLocation(); + } + + /** + * Returns the relative teleportation flags used in this teleportation. + * This determines which axis the player will not lose their velocity in. + * + * @return an immutable set of relative teleportation flags + */ + public @Unmodifiable Set getRelativeTeleportationFlags() { + return this.teleportFlags; + } + + /** + * Gets the cause of this teleportation event + * + * @return Cause of the event + */ + public PlayerTeleportEvent.TeleportCause getCause() { + return this.cause; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 596338c7c9b3..44bd4c4e40a2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -18,6 +18,7 @@ import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.PaperPlayerGiveResult; import io.papermc.paper.entity.PlayerGiveResult; +import io.papermc.paper.event.player.PlayerPrepareTeleportEvent; import io.papermc.paper.math.Angle; import io.papermc.paper.math.Position; import io.papermc.paper.util.MCUtil; @@ -1316,6 +1317,12 @@ protected boolean teleport0(Location location, org.bukkit.event.player.PlayerTel if (this.getHandle().connection == null) { return false; } + + // Paper start - Add PlayerPrepareTeleportEvent + final PlayerPrepareTeleportEvent playerPrepareTeleportEvent = new PlayerPrepareTeleportEvent(this, location, cause, Set.of(flags)); + this.server.getPluginManager().callEvent(playerPrepareTeleportEvent); + // Paper end - Add PlayerPrepareTeleportEvent + // Minecraft does not currently support teleporting players between worlds with passengers. // It causes them to be dismounted, and causes weird behavior. if (location.getWorld() != this.getWorld() && this.getHandle().isVehicle()) { From 374c1950b2240981a090181e633f671bb0cd3123 Mon Sep 17 00:00:00 2001 From: Sky Date: Thu, 13 Aug 2026 17:18:04 +0300 Subject: [PATCH 2/4] Added PlayerPrepareTeleportEvent overloads --- .../player/PlayerPrepareTeleportEvent.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java index 77adcc73882b..6c14fa51bd9e 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java @@ -1,6 +1,7 @@ package io.papermc.paper.event.player; import io.papermc.paper.entity.TeleportFlag; +import java.util.Collections; import java.util.Set; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -25,6 +26,22 @@ public class PlayerPrepareTeleportEvent extends PlayerEvent { private final PlayerTeleportEvent.TeleportCause cause; private final Set teleportFlags; + @ApiStatus.Internal + public PlayerPrepareTeleportEvent(final Player player, Location to) { + super(player); + this.to = to; + this.cause = PlayerTeleportEvent.TeleportCause.PLUGIN; + this.teleportFlags = Collections.emptySet(); + } + + @ApiStatus.Internal + public PlayerPrepareTeleportEvent(final Player player, Location to, PlayerTeleportEvent.TeleportCause cause) { + super(player); + this.to = to; + this.cause = cause; + this.teleportFlags = Collections.emptySet(); + } + @ApiStatus.Internal public PlayerPrepareTeleportEvent(final Player player, Location to, PlayerTeleportEvent.TeleportCause cause, Set teleportFlags) { super(player); From 73171098325758ecd28615ccc5c57c019f988b40 Mon Sep 17 00:00:00 2001 From: Sky Date: Mon, 17 Aug 2026 12:47:07 +0300 Subject: [PATCH 3/4] Ensure Immutability of teleportFlags --- .../papermc/paper/event/player/PlayerPrepareTeleportEvent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java index 6c14fa51bd9e..d630797b81aa 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java @@ -1,5 +1,6 @@ package io.papermc.paper.event.player; +import com.google.common.collect.ImmutableSet; import io.papermc.paper.entity.TeleportFlag; import java.util.Collections; import java.util.Set; @@ -47,7 +48,7 @@ public PlayerPrepareTeleportEvent(final Player player, Location to, PlayerTelepo super(player); this.to = to; this.cause = cause; - this.teleportFlags = teleportFlags; + this.teleportFlags = ImmutableSet.copyOf(teleportFlags); } /** From d93cb5c8ee596d400c7efc7a5c16f5b367ffa200 Mon Sep 17 00:00:00 2001 From: Sky Date: Mon, 17 Aug 2026 19:40:06 +0300 Subject: [PATCH 4/4] Replace ImmutableSet with Set --- .../papermc/paper/event/player/PlayerPrepareTeleportEvent.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java index d630797b81aa..868d8a5054dd 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPrepareTeleportEvent.java @@ -1,6 +1,5 @@ package io.papermc.paper.event.player; -import com.google.common.collect.ImmutableSet; import io.papermc.paper.entity.TeleportFlag; import java.util.Collections; import java.util.Set; @@ -48,7 +47,7 @@ public PlayerPrepareTeleportEvent(final Player player, Location to, PlayerTelepo super(player); this.to = to; this.cause = cause; - this.teleportFlags = ImmutableSet.copyOf(teleportFlags); + this.teleportFlags = Set.copyOf(teleportFlags); } /**