From 07f924343fd672424f58eb1acc23eb9ea6b727b9 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Tue, 25 May 2021 08:24:08 +1000 Subject: [PATCH] SPIGOT-6133: Chorus fruit consumption calls PlayerTeleportEvent multiple times By: DerFrZocker --- .../server/network/PlayerConnection.patch | 55 +++++------ .../minecraft/world/entity/EntityLiving.patch | 92 ++++++++++++++----- .../world/item/ItemChorusFruit.patch | 49 ++++------ 3 files changed, 112 insertions(+), 84 deletions(-) diff --git a/paper-server/nms-patches/net/minecraft/server/network/PlayerConnection.patch b/paper-server/nms-patches/net/minecraft/server/network/PlayerConnection.patch index 4deb59963f..6b299ff7b5 100644 --- a/paper-server/nms-patches/net/minecraft/server/network/PlayerConnection.patch +++ b/paper-server/nms-patches/net/minecraft/server/network/PlayerConnection.patch @@ -565,7 +565,7 @@ if (flag) { this.player.fallDistance = 0.0F; } -@@ -957,10 +1272,66 @@ +@@ -957,10 +1272,67 @@ } public void a(double d0, double d1, double d2, float f, float f1) { @@ -582,7 +582,7 @@ + this.a(d0, d1, d2, f, f1, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); + } + -+ public void a(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { ++ public boolean a(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status + Player player = this.getPlayer(); + Location from = player.getLocation(); + @@ -596,7 +596,7 @@ + // SPIGOT-5171: Triggered on join + if (from.equals(to)) { + this.internalTeleport(d0, d1, d2, f, f1, set); -+ return; ++ return false; // CraftBukkit - Return event status + } + + PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); @@ -613,6 +613,7 @@ + } + + this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status + } + + public void teleport(Location dest) { @@ -633,7 +634,7 @@ double d3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X) ? this.player.locX() : 0.0D; double d4 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y) ? this.player.locY() : 0.0D; double d5 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Z) ? this.player.locZ() : 0.0D; -@@ -972,6 +1343,14 @@ +@@ -972,6 +1344,14 @@ this.teleportAwait = 0; } @@ -648,7 +649,7 @@ this.A = this.e; this.player.setLocation(d0, d1, d2, f, f1); this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); -@@ -980,6 +1359,7 @@ +@@ -980,6 +1360,7 @@ @Override public void a(PacketPlayInBlockDig packetplayinblockdig) { PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.getWorldServer()); @@ -656,7 +657,7 @@ BlockPosition blockposition = packetplayinblockdig.b(); this.player.resetIdleTimer(); -@@ -990,14 +1370,46 @@ +@@ -990,14 +1371,46 @@ if (!this.player.isSpectator()) { ItemStack itemstack = this.player.b(EnumHand.OFF_HAND); @@ -705,7 +706,7 @@ this.player.dropItem(false); } -@@ -1034,6 +1446,7 @@ +@@ -1034,6 +1447,7 @@ @Override public void a(PacketPlayInUseItem packetplayinuseitem) { PlayerConnectionUtils.ensureMainThread(packetplayinuseitem, this, this.player.getWorldServer()); @@ -713,7 +714,7 @@ WorldServer worldserver = this.player.getWorldServer(); EnumHand enumhand = packetplayinuseitem.b(); ItemStack itemstack = this.player.b(enumhand); -@@ -1044,6 +1457,14 @@ +@@ -1044,6 +1458,14 @@ this.player.resetIdleTimer(); if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { @@ -728,7 +729,7 @@ EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); if (enumdirection == EnumDirection.UP && !enuminteractionresult.a() && blockposition.getY() >= this.minecraftServer.getMaxBuildHeight() - 1 && a(this.player, itemstack)) { -@@ -1067,12 +1488,51 @@ +@@ -1067,12 +1489,51 @@ @Override public void a(PacketPlayInBlockPlace packetplayinblockplace) { PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.getWorldServer()); @@ -780,7 +781,7 @@ EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand); if (enuminteractionresult.b()) { -@@ -1093,7 +1553,7 @@ +@@ -1093,7 +1554,7 @@ Entity entity = packetplayinspectate.a(worldserver); if (entity != null) { @@ -789,7 +790,7 @@ return; } } -@@ -1102,7 +1562,12 @@ +@@ -1102,7 +1563,12 @@ } @Override @@ -803,7 +804,7 @@ @Override public void a(PacketPlayInBoatMove packetplayinboatmove) { -@@ -1117,11 +1582,26 @@ +@@ -1117,11 +1583,26 @@ @Override public void a(IChatBaseComponent ichatbasecomponent) { @@ -831,7 +832,7 @@ ITextFilter itextfilter = this.player.Q(); if (itextfilter != null) { -@@ -1153,6 +1633,15 @@ +@@ -1153,6 +1634,15 @@ } } @@ -847,7 +848,7 @@ try { this.networkManager.sendPacket(packet, genericfuturelistener); } catch (Throwable throwable) { -@@ -1169,7 +1658,16 @@ +@@ -1169,7 +1659,16 @@ @Override public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) { PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); @@ -864,7 +865,7 @@ if (this.player.inventory.itemInHandIndex != packetplayinhelditemslot.b() && this.player.getRaisedHand() == EnumHand.MAIN_HAND) { this.player.clearActiveItem(); } -@@ -1178,65 +1676,286 @@ +@@ -1178,65 +1677,286 @@ this.player.resetIdleTimer(); } else { PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); @@ -1160,7 +1161,7 @@ this.player.resetIdleTimer(); IJumpable ijumpable; -@@ -1294,6 +2013,7 @@ +@@ -1294,6 +2014,7 @@ @Override public void a(PacketPlayInUseEntity packetplayinuseentity) { PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.getWorldServer()); @@ -1168,7 +1169,7 @@ WorldServer worldserver = this.player.getWorldServer(); Entity entity = packetplayinuseentity.a((World) worldserver); -@@ -1307,18 +2027,72 @@ +@@ -1307,18 +2028,72 @@ ItemStack itemstack = enumhand != null ? this.player.b(enumhand).cloneItemStack() : ItemStack.b; Optional optional = Optional.empty(); @@ -1242,7 +1243,7 @@ } if (optional.isPresent() && ((EnumInteractionResult) optional.get()).a()) { -@@ -1365,15 +2139,21 @@ +@@ -1365,15 +2140,21 @@ @Override public void a(PacketPlayInCloseWindow packetplayinclosewindow) { PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); @@ -1266,7 +1267,7 @@ NonNullList nonnulllist = NonNullList.a(); for (int i = 0; i < this.player.activeContainer.slots.size(); ++i) { -@@ -1382,8 +2162,285 @@ +@@ -1382,8 +2163,285 @@ this.player.a(this.player.activeContainer, nonnulllist); } else { @@ -1553,7 +1554,7 @@ if (ItemStack.matches(packetplayinwindowclick.f(), itemstack)) { this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.b(), packetplayinwindowclick.e(), true)); this.player.e = true; -@@ -1423,6 +2480,7 @@ +@@ -1423,6 +2481,7 @@ @Override public void a(PacketPlayInEnchantItem packetplayinenchantitem) { PlayerConnectionUtils.ensureMainThread(packetplayinenchantitem, this, this.player.getWorldServer()); @@ -1561,7 +1562,7 @@ this.player.resetIdleTimer(); if (this.player.activeContainer.windowId == packetplayinenchantitem.b() && this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { this.player.activeContainer.a((EntityHuman) this.player, packetplayinenchantitem.c()); -@@ -1455,6 +2513,43 @@ +@@ -1455,6 +2514,43 @@ boolean flag1 = packetplayinsetcreativeslot.b() >= 1 && packetplayinsetcreativeslot.b() <= 45; boolean flag2 = itemstack.isEmpty() || itemstack.getDamage() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); @@ -1605,7 +1606,7 @@ if (flag1 && flag2) { if (itemstack.isEmpty()) { -@@ -1476,6 +2571,7 @@ +@@ -1476,6 +2572,7 @@ @Override public void a(PacketPlayInTransaction packetplayintransaction) { PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.getWorldServer()); @@ -1613,7 +1614,7 @@ int i = this.player.activeContainer.windowId; if (i == packetplayintransaction.b() && this.k.getOrDefault(i, (short) (packetplayintransaction.c() + 1)) == packetplayintransaction.c() && !this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { -@@ -1494,6 +2590,7 @@ +@@ -1494,6 +2591,7 @@ } private void a(PacketPlayInUpdateSign packetplayinupdatesign, List list) { @@ -1621,7 +1622,7 @@ this.player.resetIdleTimer(); WorldServer worldserver = this.player.getWorldServer(); BlockPosition blockposition = packetplayinupdatesign.b(); -@@ -1510,12 +2607,28 @@ +@@ -1510,12 +2608,28 @@ if (!tileentitysign.d() || tileentitysign.f() != this.player) { PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getDisplayName().getString()); @@ -1651,7 +1652,7 @@ tileentitysign.update(); worldserver.notify(blockposition, iblockdata, iblockdata, 3); -@@ -1525,6 +2638,7 @@ +@@ -1525,6 +2639,7 @@ @Override public void a(PacketPlayInKeepAlive packetplayinkeepalive) { @@ -1659,7 +1660,7 @@ if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); -@@ -1539,7 +2653,17 @@ +@@ -1539,7 +2654,17 @@ @Override public void a(PacketPlayInAbilities packetplayinabilities) { PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.getWorldServer()); @@ -1678,7 +1679,7 @@ } @Override -@@ -1548,8 +2672,50 @@ +@@ -1548,8 +2673,50 @@ this.player.a(packetplayinsettings); } diff --git a/paper-server/nms-patches/net/minecraft/world/entity/EntityLiving.patch b/paper-server/nms-patches/net/minecraft/world/entity/EntityLiving.patch index 05a9761b07..18703b0410 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/EntityLiving.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/EntityLiving.patch @@ -689,7 +689,10 @@ + } + } + } -+ + +- f = Math.max(f - this.getAbsorptionHearts(), 0.0F); +- this.setAbsorptionHearts(this.getAbsorptionHearts() - (f1 - f)); +- float f2 = f1 - f; + // Apply damage to helmet + if ((damagesource == DamageSource.ANVIL || damagesource == DamageSource.FALLING_BLOCK) && this.getEquipment(EnumItemSlot.HEAD) != null) { + this.getEquipment(EnumItemSlot.HEAD).damage((int) (event.getDamage() * 4.0F + this.random.nextFloat() * event.getDamage() * 2.0F), this, (entityliving) -> { @@ -703,15 +706,12 @@ + this.damageArmor(damagesource, armorDamage); + } -- f = Math.max(f - this.getAbsorptionHearts(), 0.0F); -- this.setAbsorptionHearts(this.getAbsorptionHearts() - (f1 - f)); -- float f2 = f1 - f; + // Apply blocking code // PAIL: steal from above + if (event.getDamage(DamageModifier.BLOCKING) < 0) { + this.world.broadcastEntityEffect(this, (byte) 29); // SPIGOT-4635 - shield damage sound + this.damageShield((float) -event.getDamage(DamageModifier.BLOCKING)); + Entity entity = damagesource.j(); - ++ + if (entity instanceof EntityLiving) { + this.shieldBlock((EntityLiving) entity); + } @@ -833,7 +833,7 @@ Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); -@@ -2548,14 +2980,21 @@ +@@ -2548,13 +2980,20 @@ @Override public boolean isInteractable() { @@ -845,18 +845,17 @@ public boolean isCollidable() { - return this.isAlive() && !this.isSpectator() && !this.isClimbing(); + return this.isAlive() && !this.isSpectator() && !this.isClimbing() && this.collides; // CraftBukkit - } - ++ } ++ + // CraftBukkit start - collidable API + @Override + public boolean canCollideWith(Entity entity) { + return isCollidable() && this.collides != this.collidableExemptions.contains(entity.getUniqueID()); -+ } + } + // CraftBukkit end -+ + @Override protected void velocityChanged() { - this.velocityChanged = this.random.nextDouble() >= this.b(GenericAttributes.KNOCKBACK_RESISTANCE); @@ -2748,7 +3187,25 @@ } else { if (!this.activeItem.isEmpty() && this.isHandRaised()) { @@ -884,29 +883,74 @@ if (itemstack != this.activeItem) { this.a(enumhand, itemstack); -@@ -2840,10 +3297,18 @@ +@@ -2816,6 +3273,12 @@ + } + + public boolean a(double d0, double d1, double d2, boolean flag) { ++ // CraftBukkit start ++ return safeTeleport(d0, d1, d2, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } ++ ++ public Optional safeTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + double d3 = this.locX(); + double d4 = this.locY(); + double d5 = this.locZ(); +@@ -2840,16 +3303,41 @@ } if (flag2) { - this.enderTeleportTo(d0, d6, d2); -- if (world.getCubes(this) && !world.containsLiquid(this.getBoundingBox())) { -- flag1 = true; + // CraftBukkit start - Teleport event + // this.enderTeleportTo(d0, d6, d2); -+ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.world.getWorld(), d3, d4, d5), new Location(this.world.getWorld(), d0, d6, d2)); -+ this.world.getServer().getPluginManager().callEvent(teleport); -+ if (!teleport.isCancelled()) { -+ Location to = teleport.getTo(); -+ this.enderTeleportTo(to.getX(), to.getY(), to.getZ()); -+ if (world.getCubes(this) && !world.containsLiquid(this.getBoundingBox())) { -+ flag1 = true; -+ } ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPosition(d0, d6, d2); + if (world.getCubes(this) && !world.containsLiquid(this.getBoundingBox())) { + flag1 = true; } ++ // now revert and call event if the teleport place is valid ++ this.setPosition(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof EntityPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.world.getWorld(), d3, d4, d5), new Location(this.world.getWorld(), d0, d6, d2)); ++ this.world.getServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.enderTeleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((EntityPlayer) this).playerConnection.a(d0, d6, d2, this.yaw, this.pitch, java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } + // CraftBukkit end } } -@@ -2940,7 +3405,7 @@ + if (!flag1) { +- this.enderTeleportTo(d3, d4, d5); +- return false; ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (flag) { + world.broadcastEntityEffect(this, (byte) 46); +@@ -2859,7 +3347,7 @@ + ((EntityCreature) this).getNavigation().o(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -2940,7 +3428,7 @@ } public void entityWakeup() { @@ -915,7 +959,7 @@ World world = this.world; this.world.getClass(); -@@ -3011,7 +3476,7 @@ +@@ -3011,7 +3499,7 @@ Pair pair = (Pair) iterator.next(); if (!world.isClientSide && pair.getFirst() != null && world.random.nextFloat() < (Float) pair.getSecond()) { diff --git a/paper-server/nms-patches/net/minecraft/world/item/ItemChorusFruit.patch b/paper-server/nms-patches/net/minecraft/world/item/ItemChorusFruit.patch index 1a296a4db2..43951c70c9 100644 --- a/paper-server/nms-patches/net/minecraft/world/item/ItemChorusFruit.patch +++ b/paper-server/nms-patches/net/minecraft/world/item/ItemChorusFruit.patch @@ -1,37 +1,20 @@ --- a/net/minecraft/world/item/ItemChorusFruit.java +++ b/net/minecraft/world/item/ItemChorusFruit.java -@@ -9,6 +9,13 @@ - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; - -+// CraftBukkit start -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.bukkit.event.player.PlayerTeleportEvent; -+// CraftBukkit end -+ - public class ItemChorusFruit extends Item { - - public ItemChorusFruit(Item.Info item_info) { -@@ -29,6 +36,20 @@ - double d4 = MathHelper.a(entityliving.locY() + (double) (entityliving.getRandom().nextInt(16) - 8), 0.0D, (double) (world.getHeight() - 1)); - double d5 = entityliving.locZ() + (entityliving.getRandom().nextDouble() - 0.5D) * 16.0D; - -+ // CraftBukkit start -+ if (entityliving instanceof EntityPlayer) { -+ Player player = ((EntityPlayer) entityliving).getBukkitEntity(); -+ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), new Location(player.getWorld(), d3, d4, d5), PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); -+ world.getServer().getPluginManager().callEvent(teleEvent); -+ if (teleEvent.isCancelled()) { -+ break; -+ } -+ d3 = teleEvent.getTo().getX(); -+ d4 = teleEvent.getTo().getY(); -+ d5 = teleEvent.getTo().getZ(); -+ } -+ // CraftBukkit end -+ - if (entityliving.isPassenger()) { +@@ -33,7 +33,16 @@ entityliving.stopRiding(); } + +- if (entityliving.a(d3, d4, d5, true)) { ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityliving.safeTeleport(d3, d4, d5, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); ++ ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end + SoundEffect soundeffect = entityliving instanceof EntityFox ? SoundEffects.ENTITY_FOX_TELEPORT : SoundEffects.ITEM_CHORUS_FRUIT_TELEPORT; + + world.playSound((EntityHuman) null, d0, d1, d2, soundeffect, SoundCategory.PLAYERS, 1.0F, 1.0F);