From 021305dc62267e55bde61e927c2d95ced6f5a0ff Mon Sep 17 00:00:00 2001 From: Minecrell <minecrell@minecrell.net> Date: Fri, 13 Jul 2018 09:48:51 +0200 Subject: [PATCH] Avoid visual issues for adjacent blocks when cancelling PIE (#1198) The adjacent blocks of doors, double plants, pistons and beds need to be updated manually from the server when cancelling a block break from a player, as it otherwise causes the other parts to disappear on the client. This is already done for doors but only for the BlockBreakEvent, not for PlayerInteractEvent. Move the code to a common method and also handle the other blocks in similar ways. --- .../Extend-Player-Interact-cancellation.patch | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch b/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch index 7f0d84b5d9..764fecb8db 100644 --- a/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch +++ b/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch @@ -9,10 +9,69 @@ However, it is possible to close these GUIs from the server. Flower pots are also not updated on the client when interaction is cancelled, this patch also resolves this. +Update adjacent blocks of doors, double plants, pistons and beds +when cancelling interaction. + diff --git a/src/main/java/net/minecraft/server/PlayerInteractManager.java b/src/main/java/net/minecraft/server/PlayerInteractManager.java -index 5ec7f5819..24f14337a 100644 +index 5ec7f5819..fcb64666e 100644 --- a/src/main/java/net/minecraft/server/PlayerInteractManager.java +++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java +@@ -0,0 +0,0 @@ public class PlayerInteractManager { + if (event.isCancelled()) { + // Let the client know the block still exists + ((EntityPlayer) this.player).playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); ++ cancelBreakBlock(blockposition, this.world.getType(blockposition)); // Paper - Avoid visual issues on the client + // Update any tile entity data for this block + TileEntity tileentity = this.world.getTileEntity(blockposition); + if (tileentity != null) { +@@ -0,0 +0,0 @@ public class PlayerInteractManager { + return flag; + } + ++ // Paper start - Extra method to avoid visual issues on the client when cancelling block breaks ++ private void cancelBreakBlock(BlockPosition position, IBlockData data) { ++ Block block = data.getBlock(); ++ // Send other half of the door ++ if (block instanceof BlockDoor) { ++ boolean bottom = data.get(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER; ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, bottom ? position.up() : position.down())); ++ } else if (block instanceof BlockTallPlant) { ++ boolean bottom = data.get(BlockTallPlant.HALF) == BlockTallPlant.EnumTallPlantHalf.LOWER; ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, bottom ? position.up() : position.down())); ++ } else if (block instanceof BlockPistonExtension) { ++ BlockPosition piston = position.shift(data.get(BlockPistonExtension.FACING).opposite()); ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, piston)); ++ } else if (block instanceof BlockBed) { ++ if (data.get(BlockBed.PART) == BlockBed.EnumBedPart.FOOT) { ++ // Restore head of bed ++ BlockPosition head = position.shift(data.get(BlockBed.FACING)); ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, head)); ++ ++ TileEntity tileentity = this.world.getTileEntity(head); ++ if (tileentity != null) { ++ this.player.playerConnection.sendPacket(tileentity.getUpdatePacket()); ++ } ++ } ++ } ++ } ++ // Paper end ++ + public boolean breakBlock(BlockPosition blockposition) { + // CraftBukkit start - fire BlockBreakEvent + BlockBreakEvent event = null; +@@ -0,0 +0,0 @@ public class PlayerInteractManager { + } + // Let the client know the block still exists + ((EntityPlayer) this.player).playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); +- // Send other half of the door +- if (nmsBlock instanceof BlockDoor) { +- boolean bottom = nmsData.get(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER; +- ((EntityPlayer) this.player).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, bottom ? blockposition.up() : blockposition.down())); +- } ++ cancelBreakBlock(blockposition, nmsData); // Paper - Move cancellation code to extra "cancelBreakBlock" method + // Update any tile entity data for this block + TileEntity tileentity = this.world.getTileEntity(blockposition); + if (tileentity != null) { @@ -0,0 +0,0 @@ public class PlayerInteractManager { ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, bottom ? blockposition.up() : blockposition.down())); } else if (blockdata.getBlock() instanceof BlockCake) {