From d9d8c38c297e31906d99fba22f1ad10dc75a4f31 Mon Sep 17 00:00:00 2001 From: leguan Date: Wed, 17 Jan 2024 22:03:21 +0100 Subject: [PATCH] Add PreTeleportEvents --- patches/api/0475-Add-PreTeleportEvents.patch | 170 +++++++++++++ .../server/1046-Add-PreTeleportEvents.patch | 232 ++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 patches/api/0475-Add-PreTeleportEvents.patch create mode 100644 patches/server/1046-Add-PreTeleportEvents.patch diff --git a/patches/api/0475-Add-PreTeleportEvents.patch b/patches/api/0475-Add-PreTeleportEvents.patch new file mode 100644 index 0000000000..45254be8da --- /dev/null +++ b/patches/api/0475-Add-PreTeleportEvents.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: leguan +Date: Wed, 17 Jan 2024 19:58:51 +0100 +Subject: [PATCH] Add PreTeleportEvents + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityPreTeleportEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityPreTeleportEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fff2baf06a0061d95d382cf25e633ab84a295b51 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityPreTeleportEvent.java +@@ -0,0 +1,70 @@ ++package io.papermc.paper.event.entity; ++ ++import io.papermc.paper.entity.TeleportFlag; ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.jetbrains.annotations.NotNull; ++import java.util.Collections; ++import java.util.Set; ++ ++/** ++ * Called before an {@link Entity} is teleported. ++ * This is helpful if certain preparations have to me made in order for the teleport to happen. ++ */ ++public class EntityPreTeleportEvent extends EntityEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Location from; ++ private final Location to; ++ private final Set flags; ++ ++ public EntityPreTeleportEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to) { ++ this(what, from, to, Collections.emptySet()); ++ } ++ ++ public EntityPreTeleportEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull Set flags) { ++ super(what); ++ this.from = from; ++ this.to = to; ++ this.flags = flags; ++ } ++ ++ /** ++ * Returns a clone of the player's current Location. ++ * @return A clone of the player's current location. ++ */ ++ public @NotNull Location getFrom() { ++ return from.clone(); ++ } ++ ++ /** ++ * Returns a clone of the target location. ++ * @return A clone of the target location. ++ */ ++ public @NotNull Location getTo() { ++ return to.clone(); ++ } ++ ++ /** ++ * Returns the provided flags of the teleport call. ++ * @see TeleportFlag ++ * @return The flags of the teleport call. ++ */ ++ public @NotNull Set getFlags() { ++ return flags; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPreTeleportEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPreTeleportEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8dd919ee1b0e4e130f763cd9feeb5257b07efc3c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerPreTeleportEvent.java +@@ -0,0 +1,82 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.entity.TeleportFlag; ++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.NotNull; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.Set; ++ ++/** ++ * Called before a {@link Player} is teleported. ++ * This is helpful if certain preparations have to me made in order for the teleport to happen. ++ */ ++public class PlayerPreTeleportEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Location from; ++ private final Location to; ++ private final PlayerTeleportEvent.TeleportCause cause; ++ private final Set flags; ++ ++ public PlayerPreTeleportEvent(@NotNull Player who, @NotNull Location from, @NotNull Location to, PlayerTeleportEvent.@NotNull TeleportCause cause) { ++ this(who, from, to, cause, Collections.emptySet()); ++ } ++ ++ public PlayerPreTeleportEvent(@NotNull Player who, @NotNull Location from, @NotNull Location to, PlayerTeleportEvent.@NotNull TeleportCause cause, java.util.Set flags) { ++ super(who); ++ this.from = from; ++ this.to = to; ++ this.cause = cause; ++ this.flags = flags; ++ } ++ ++ /** ++ * Returns a clone of the player's current Location. ++ * @return A clone of the player's current location. ++ */ ++ public @NotNull Location getFrom() { ++ return from.clone(); ++ } ++ ++ /** ++ * Returns a clone of the target location. ++ * @return A clone of the target location. ++ */ ++ public @NotNull Location getTo() { ++ return to.clone(); ++ } ++ ++ /** ++ * Returns the initial cause of the location. ++ * @see org.bukkit.event.player.PlayerTeleportEvent.TeleportCause ++ * @return The initial cause of the location. ++ */ ++ public PlayerTeleportEvent.@NotNull TeleportCause getCause() { ++ return cause; ++ } ++ ++ /** ++ * Returns the provided flags of the teleport call. ++ * @see TeleportFlag ++ * @return The flags of the teleport call. ++ */ ++ public @NotNull Collection getFlags() { ++ return flags; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++} diff --git a/patches/server/1046-Add-PreTeleportEvents.patch b/patches/server/1046-Add-PreTeleportEvents.patch new file mode 100644 index 0000000000..1d58db1fd3 --- /dev/null +++ b/patches/server/1046-Add-PreTeleportEvents.patch @@ -0,0 +1,232 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: leguan +Date: Wed, 17 Jan 2024 19:59:06 +0100 +Subject: [PATCH] Add PreTeleportEvents + + +diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +index 54851f6cc0d5fddb32a9a1e84a4f5ae41af18758..870e8d5ed8fcaa376d38037ad1ffdcd7169c57ff 100644 +--- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java ++++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +@@ -167,6 +167,7 @@ public class TeleportCommand { + result = player.teleportTo(world, x, y, z, movementFlags, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); + } else { + Location to = new Location(world.getWorld(), x, y, z, f2, f3); ++ (new io.papermc.paper.event.entity.EntityPreTeleportEvent(target.getBukkitEntity(), target.getBukkitEntity().getLocation(), to)).callEvent(); // Paper - Add PreTeleportEvents + EntityTeleportEvent event = new EntityTeleportEvent(target.getBukkitEntity(), target.getBukkitEntity().getLocation(), to); + world.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null) { // Paper +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 8437316888c6056060a2780652147590b6fe7443..7cc140177dd3a41bcd904f375efa0ce0ee2debe3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1288,6 +1288,11 @@ public class ServerPlayer extends Player { + */ + // CraftBukkit end + PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); ++ // Paper start - Add PreTeleportEvents ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ (new io.papermc.paper.event.player.PlayerPreTeleportEvent(this.getBukkitEntity(), enter, exit, cause)).callEvent(); ++ // Paper end - Add PreTeleportEvents + + if (shapedetectorshape != null) { + worldserver1.getProfiler().push("moving"); +@@ -1302,8 +1307,10 @@ public class ServerPlayer extends Player { + } else { + return null; + } +- Location enter = this.getBukkitEntity().getLocation(); +- Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ // Paper start - Add PreTeleportEvents - moved up ++ // Location enter = this.getBukkitEntity().getLocation(); ++ // Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ // Paper end - Add PreTeleportEvents + PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); + Bukkit.getServer().getPluginManager().callEvent(tpEvent); + if (tpEvent.isCancelled() || tpEvent.getTo() == null) { +@@ -1369,6 +1376,7 @@ public class ServerPlayer extends Player { + protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { + Location enter = this.getBukkitEntity().getLocation(); + Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), this.getYRot(), this.getXRot()); ++ (new io.papermc.paper.event.player.PlayerPreTeleportEvent(this.getBukkitEntity(), enter, exit, cause)).callEvent(); // Paper - Add PreTeleportEvents + PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 8e67853a7a93fa736c147e8b2df537746dc8e94f..1ce9f4119d153edbfd90654c11d23eb2dfe5960c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1696,7 +1696,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + for (RelativeMovement relativeArgument : set) { + relativeFlags.add(org.bukkit.craftbukkit.entity.CraftPlayer.toApiRelativeFlag(relativeArgument)); + } +- PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause, java.util.Set.copyOf(relativeFlags)); ++ // Paper start - Add PreTeleportEvents ++ Location fromLocation = from.clone(); ++ Location toLocation = to.clone(); ++ (new io.papermc.paper.event.player.PlayerPreTeleportEvent(player, fromLocation, toLocation, cause, java.util.Set.copyOf(relativeFlags))).callEvent(); ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, fromLocation, toLocation, cause, java.util.Set.copyOf(relativeFlags)); ++ // Paper end - Add PreTeleportEvents + // Paper end - Teleport API + this.cserver.getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2bc85351e6e52f90da5fdb29d8d042a06132d742..d3c111eb9823c726d5c9fa0d000a315c1e92bb3d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3872,7 +3872,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); + Location enter = bukkitEntity.getLocation(); + Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); +- ++ (new io.papermc.paper.event.entity.EntityPreTeleportEvent(bukkitEntity, enter, exit)).callEvent(); // Paper - Add PreTeleportEvents + // Paper start + final org.bukkit.PortalType portalType = switch (cause) { + case END_PORTAL -> org.bukkit.PortalType.ENDER; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 6e043457a29a890bcefd27fc5bb07c1a7e4e30f7..8b9baa215cbcc7812b79a3e16581117c9e39cc5e 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -4212,10 +4212,15 @@ public abstract class LivingEntity extends Entity implements Attackable { + + if (flag1) { + if (!(this instanceof ServerPlayer)) { +- EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ // Paper start - Add PreTeleportEvents ++ Location from = new Location(this.level().getWorld(), d3, d4, d5); ++ Location to = new Location(this.level().getWorld(), d0, d6, d2); ++ (new io.papermc.paper.event.entity.EntityPreTeleportEvent(this.getBukkitLivingEntity(), from, to)).callEvent(); ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), from, to); ++ // Paper end - Add PreTeleportEvents + this.level().getCraftServer().getPluginManager().callEvent(teleport); + if (!teleport.isCancelled() && teleport.getTo() != null) { // Paper +- Location to = teleport.getTo(); ++ to = teleport.getTo(); // Paper - Add PreTeleportEvents + this.teleportTo(to.getX(), to.getY(), to.getZ()); + } else { + return Optional.empty(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +index edd29c2f4d0151d512618115a8fb4b7423171491..d96c82563e20db3fde3e866819cbd72340a1a69b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +@@ -128,12 +128,18 @@ public class FollowOwnerGoal extends Goal { + } else if (!this.canTeleportTo(new BlockPos(x, y, z))) { + return false; + } else { ++ // Paper start - Add PreTeleportEvents ++ org.bukkit.craftbukkit.entity.CraftEntity entity = this.tamable.getBukkitEntity(); ++ Location to = new Location(entity.getWorld(),(double) x + 0.5D, (double) y, (double) z + 0.5D); ++ (new io.papermc.paper.event.entity.EntityPreTeleportEvent(entity, entity.getLocation(), to)).callEvent(); + // CraftBukkit start +- EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D); ++ EntityTeleportEvent event = new org.bukkit.event.entity.EntityTeleportEvent(entity, entity.getLocation(), to); ++ event.callEvent(); ++ // Paper end - Add PreTeleportEvents + if (event.isCancelled() || event.getTo() == null) { // Paper + return false; + } +- Location to = event.getTo(); ++ to = event.getTo(); // Paper - Add PreTeleportEvents + this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); + // CraftBukkit end + this.navigation.stop(); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java +index 5215fa54666979ef4da074ddfdb082e7274f2957..dda81f1235862b013ef78e1454552c8242270d5b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java +@@ -408,7 +408,13 @@ public class Shulker extends AbstractGolem implements VariantHolder flagSet = Set.of(flags); + boolean dismount = !flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE); + boolean ignorePassengers = flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS); ++ (new io.papermc.paper.event.entity.EntityPreTeleportEvent(this, this.getLocation(), location, flagSet)).callEvent(); // Paper - Add PreTeleportEvents + // Don't allow teleporting between worlds while keeping passengers + if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) { + return false; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index eddbbd0e9be3cb81d1030c0c9da829b9193ebc16..11abdb8d0289f90b949260a30e2f35eaf3229ee6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1405,6 +1405,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end - Teleport API + Preconditions.checkArgument(location != null, "location"); + Preconditions.checkArgument(location.getWorld() != null, "location.world"); ++ (new io.papermc.paper.event.player.PlayerPreTeleportEvent(this, this.getLocation(), location, cause, allFlags)).callEvent(); // Paper - Add PreTeleportEvents + // Paper start - Teleport passenger API + // Don't allow teleporting between worlds while keeping passengers + if (ignorePassengers && entity.isVehicle() && location.getWorld() != this.getWorld()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 5a9c68b60cf3bf694fe1fcd3b095516b6481f8a2..3f2111dca111fc35908542ba4d5b3b0e885f68e7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -2044,6 +2044,8 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - Add PreTeleportEvents - no longer required ++ /* + public static EntityTeleportEvent callEntityTeleportEvent(Entity nmsEntity, double x, double y, double z) { + CraftEntity entity = nmsEntity.getBukkitEntity(); + Location to = new Location(entity.getWorld(), x, y, z, nmsEntity.getYRot(), nmsEntity.getXRot()); +@@ -2053,7 +2055,8 @@ public class CraftEventFactory { + + return event; + } +- ++ */ ++ // Paper end - Add PreTeleportEvents + public static boolean callEntityInteractEvent(Entity nmsEntity, Block block) { + EntityInteractEvent event = new EntityInteractEvent(nmsEntity.getBukkitEntity(), block); + Bukkit.getPluginManager().callEvent(event);