From 15d23a11f83273f941885c6caf170190236540a9 Mon Sep 17 00:00:00 2001 From: Mariell Date: Sat, 9 Jan 2021 17:46:20 +0100 Subject: [PATCH] Add EntityTeleportHinderedEvent (#136) --- ...0038-Add-EntityTeleportHinderedEvent.patch | 141 +++++++++++++++++ ...0168-Add-EntityTeleportHinderedEvent.patch | 147 ++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 patches/api/0038-Add-EntityTeleportHinderedEvent.patch create mode 100644 patches/server/0168-Add-EntityTeleportHinderedEvent.patch diff --git a/patches/api/0038-Add-EntityTeleportHinderedEvent.patch b/patches/api/0038-Add-EntityTeleportHinderedEvent.patch new file mode 100644 index 000000000..587b3f0e8 --- /dev/null +++ b/patches/api/0038-Add-EntityTeleportHinderedEvent.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 9 Jan 2021 15:26:04 +0100 +Subject: [PATCH] Add EntityTeleportHinderedEvent + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +diff --git a/src/main/java/net/pl3x/purpur/event/entity/EntityTeleportHinderedEvent.java b/src/main/java/net/pl3x/purpur/event/entity/EntityTeleportHinderedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6fcc4027cb70061b804460b39e00cca273d35ad +--- /dev/null ++++ b/src/main/java/net/pl3x/purpur/event/entity/EntityTeleportHinderedEvent.java +@@ -0,0 +1,117 @@ ++package net.pl3x.purpur.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Fired when an entity is hindered from teleporting. ++ */ ++public class EntityTeleportHinderedEvent extends EntityEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ private final Reason reason; ++ ++ @Nullable ++ private final TeleportCause teleportCause; ++ ++ private boolean retry = false; ++ ++ public EntityTeleportHinderedEvent(@NotNull Entity what, @NotNull Reason reason, ++ @Nullable TeleportCause teleportCause) { ++ super(what); ++ this.reason = reason; ++ this.teleportCause = teleportCause; ++ } ++ ++ /** ++ * @return why the teleport was hindered. ++ */ ++ @NotNull ++ public Reason getReason() { ++ return reason; ++ } ++ ++ /** ++ * @return why the teleport occurred if cause was given, otherwise {@code null}. ++ */ ++ @Nullable ++ public TeleportCause getTeleportCause() { ++ return teleportCause; ++ } ++ ++ /** ++ * Whether the teleport should be retried. ++ *

++ * Note that this can put the server in a never-ending loop of trying to teleport someone resulting in a stack ++ * overflow. Do not retry more than necessary. ++ *

++ * ++ * @return whether the teleport should be retried. ++ */ ++ public boolean shouldRetry() { ++ return retry; ++ } ++ ++ /** ++ * Sets whether the teleport should be retried. ++ *

++ * Note that this can put the server in a never-ending loop of trying to teleport someone resulting in a stack ++ * overflow. Do not retry more than necessary. ++ *

++ * ++ * @param retry whether the teleport should be retried. ++ */ ++ public void setShouldRetry(boolean retry) { ++ this.retry = retry; ++ } ++ ++ /** ++ * Calls the event and tests if should retry. ++ * ++ * @return whether the teleport should be retried. ++ */ ++ @Override ++ public boolean callEvent() { ++ super.callEvent(); ++ return shouldRetry(); ++ } ++ ++ @Override ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ /** ++ * Reason for hindrance in teleports. ++ */ ++ public enum Reason { ++ /** ++ * The teleported entity is a passenger of another entity. ++ */ ++ IS_PASSENGER, ++ ++ /** ++ * The teleported entity has passengers. ++ */ ++ IS_VEHICLE, ++ ++ /** ++ * The teleport event was cancelled. ++ *

++ * This is only caused by players teleporting. ++ *

++ */ ++ EVENT_CANCELLED, ++ } ++} diff --git a/patches/server/0168-Add-EntityTeleportHinderedEvent.patch b/patches/server/0168-Add-EntityTeleportHinderedEvent.patch new file mode 100644 index 000000000..8c9f3fdb2 --- /dev/null +++ b/patches/server/0168-Add-EntityTeleportHinderedEvent.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 9 Jan 2021 15:27:46 +0100 +Subject: [PATCH] Add EntityTeleportHinderedEvent + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java +index b40f5167d2a9772658c115091f13706fbb4959b7..657885cdaa086293f6b5aa6f3058acd16df0ba35 100644 +--- a/src/main/java/net/minecraft/server/BlockBase.java ++++ b/src/main/java/net/minecraft/server/BlockBase.java +@@ -250,6 +250,7 @@ public abstract class BlockBase { + return 0; + } + ++ @Deprecated public final void collideWithBlock(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { this.a(iblockdata, world, blockposition, entity); } // Purpur - OBFHELPER + @Deprecated + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) {} + +diff --git a/src/main/java/net/minecraft/server/BlockEnderPortal.java b/src/main/java/net/minecraft/server/BlockEnderPortal.java +index e731b6d811d179f07f84278d2cce75e0d98092ab..f0e5c378c4612192c1d4c74aa81e598f9370b8b8 100644 +--- a/src/main/java/net/minecraft/server/BlockEnderPortal.java ++++ b/src/main/java/net/minecraft/server/BlockEnderPortal.java +@@ -25,7 +25,15 @@ public class BlockEnderPortal extends BlockTileEntity { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { +- if (world instanceof WorldServer && !entity.isPassenger() && !entity.isVehicle() && entity.canPortal() && VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { ++ // Purpur start ++ if (world instanceof WorldServer && /*!entity.isPassenger() && !entity.isVehicle() &&*/ entity.canPortal() && VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { ++ if (entity.isPassenger() || entity.isVehicle()) { ++ if (new net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, PlayerTeleportEvent.TeleportCause.END_PORTAL).callEvent()) { ++ this.collideWithBlock(iblockdata, world, blockposition, entity); ++ } ++ return; ++ } ++ // Purpur end + ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + WorldServer worldserver = ((WorldServer) world).getMinecraftServer().getWorldServer(resourcekey); + +diff --git a/src/main/java/net/minecraft/server/BlockPortal.java b/src/main/java/net/minecraft/server/BlockPortal.java +index 4132cd4c6f13cfa1c0cda43daaa908ff3c07f32b..6dab6ee15f34c401bfe71041f46a9d5b9732770b 100644 +--- a/src/main/java/net/minecraft/server/BlockPortal.java ++++ b/src/main/java/net/minecraft/server/BlockPortal.java +@@ -63,7 +63,15 @@ public class BlockPortal extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { +- if (!entity.isPassenger() && !entity.isVehicle() && entity.canPortal()) { ++ // Purpur start ++ if (/*!entity.isPassenger() && !entity.isVehicle() &&*/ entity.canPortal()) { ++ if (entity.isPassenger() || entity.isVehicle()) { ++ if (new net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.NETHER_PORTAL).callEvent()) { ++ this.collideWithBlock(iblockdata, world, blockposition, entity); ++ } ++ return; ++ } ++ // Purpur end + // CraftBukkit start - Entity in portal + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); + world.getServer().getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java +index ed8e91bf6c8b9d410d439bdddd5067d346a20a7e..127b5d8215f2bb4c5c523c5a77ebccfbf5fc25ff 100644 +--- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java +@@ -125,9 +125,18 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick + } + } + ++ public final void teleportEntity(Entity entity) { this.b(entity); } // Purpur - OBFHELPER + public void b(Entity entity) { + if (this.world instanceof WorldServer && !this.f()) { + if (!entity.canPortal()) return; // Purpur ++ // Purpur start ++ if (this.world.purpurConfig.imposeTeleportRestrictionsOnGateways && (entity.isVehicle() || entity.isPassenger())) { ++ if (new net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, PlayerTeleportEvent.TeleportCause.END_GATEWAY).callEvent()) { ++ this.teleportEntity(entity); ++ } ++ return; ++ } ++ // Purpur end + this.c = 100; + if (this.exitPortal == null && this.world.getTypeKey() == DimensionManager.THE_END) { // CraftBukkit - work in alternate worlds + this.a((WorldServer) this.world); +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index fc5b4f1ec8bbe50522cdbcb74e5870e79ed15070..f5fd4ac62c4e2b300930356a7f5735e76f16f8a4 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -1861,4 +1861,9 @@ public class PurpurWorldConfig { + zombieVillagerMaxHealth = getDouble("mobs.zombie_villager.attributes.max_health", zombieVillagerMaxHealth); + zombieVillagerSpawnReinforcements = getDouble("mobs.zombie_villager.attributes.spawn_reinforcements", zombieVillagerSpawnReinforcements); + } ++ ++ public boolean imposeTeleportRestrictionsOnGateways = false; ++ private void imposeTeleportRestrictionsOnGateways() { ++ imposeTeleportRestrictionsOnGateways = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-gateways", imposeTeleportRestrictionsOnGateways); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index b56ca054b37f5887e13b481baad8132f1d28638b..eb0ce05d25ba33626d2dd3e3380d805c560bfe58 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -521,6 +521,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + location.checkFinite(); + + if (entity.isVehicle() || entity.dead) { ++ // Purpur start ++ if (!entity.dead && new net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, cause).callEvent()) ++ return teleport(location, cause); ++ // Purpur end + 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 4f42bc21839086b2a40a35910a08d9b11c7649f9..f3aa7878d281ae5a147728f2b5addd5659f9a6bd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -116,6 +116,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Player; + import org.bukkit.event.player.PlayerRegisterChannelEvent; + import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; + import org.bukkit.event.player.PlayerUnregisterChannelEvent; + import org.bukkit.inventory.InventoryView.Property; + import org.bukkit.inventory.ItemStack; +@@ -791,6 +792,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + if (entity.isVehicle()) { ++ // Purpur start ++ if (new net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), net.pl3x.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, cause).callEvent()) ++ return teleport(location, cause); ++ // Purpur end + return false; + } +