Commits

FreeSoccerHDX authored and md_5 committed 8e1bdeef508
SPIGOT-6910: Add BlockDamageAbortEvent
No tags

nms-patches/net/minecraft/server/level/PlayerInteractManager.patch

Modified
53 53
54 54 @@ -86,7 +114,7 @@
55 55 }
56 56
57 57 public void tick() {
58 58 - ++this.gameTicks;
59 59 + this.gameTicks = MinecraftServer.currentTick; // CraftBukkit;
60 60 IBlockData iblockdata;
61 61
62 62 if (this.hasDelayedDestroy) {
63 -@@ -142,9 +170,31 @@
63 +@@ -142,10 +170,32 @@
64 64
65 65 if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) {
66 66 if (!this.level.mayInteract(this.player, blockposition)) {
67 67 + // CraftBukkit start - fire PlayerInteractEvent
68 68 + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND);
69 69 this.player.connection.send(new PacketPlayOutBlockBreak(blockposition, this.level.getBlockState(blockposition), packetplayinblockdig_enumplayerdigtype, false, "may not interact"));
70 70 + // Update any tile entity data for this block
71 71 + TileEntity tileentity = level.getBlockEntity(blockposition);
72 72 + if (tileentity != null) {
73 73 + this.player.connection.send(tileentity.getUpdatePacket());
74 74 + }
75 75 + // CraftBukkit end
76 -+ return;
77 -+ }
78 -+
76 + return;
77 + }
78 +
79 79 + // CraftBukkit start
80 80 + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND);
81 81 + if (event.isCancelled()) {
82 82 + // Let the client know the block still exists
83 83 + this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition));
84 84 + // Update any tile entity data for this block
85 85 + TileEntity tileentity = this.level.getBlockEntity(blockposition);
86 86 + if (tileentity != null) {
87 87 + this.player.connection.send(tileentity.getUpdatePacket());
88 88 + }
89 - return;
90 - }
89 ++ return;
90 ++ }
91 91 + // CraftBukkit end
92 -
92 ++
93 93 if (this.isCreative()) {
94 94 this.destroyAndAck(blockposition, packetplayinblockdig_enumplayerdigtype, "creative destroy");
95 + return;
95 96 @@ -160,11 +210,43 @@
96 97 float f = 1.0F;
97 98
98 99 iblockdata = this.level.getBlockState(blockposition);
99 100 - if (!iblockdata.isAir()) {
100 101 + // CraftBukkit start - Swings at air do *NOT* exist.
101 102 + if (event.useInteractedBlock() == Event.Result.DENY) {
102 103 + // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door.
103 104 + IBlockData data = this.level.getBlockState(blockposition);
104 105 + if (data.getBlock() instanceof BlockDoor) {
130 131 + }
131 132 +
132 133 + if (blockEvent.getInstaBreak()) {
133 134 + f = 2.0f;
134 135 + }
135 136 + // CraftBukkit end
136 137 +
137 138 if (!iblockdata.isAir() && f >= 1.0F) {
138 139 this.destroyAndAck(blockposition, packetplayinblockdig_enumplayerdigtype, "insta mine");
139 140 } else {
140 -@@ -208,7 +290,7 @@
141 +@@ -208,13 +290,15 @@
141 142 } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) {
142 143 this.isDestroyingBlock = false;
143 144 if (!Objects.equals(this.destroyPos, blockposition)) {
144 145 - PlayerInteractManager.LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, blockposition);
145 146 + PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled
146 147 this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
147 148 this.player.connection.send(new PacketPlayOutBlockBreak(this.destroyPos, this.level.getBlockState(this.destroyPos), packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying"));
148 149 }
149 -@@ -224,17 +306,72 @@
150 +
151 + this.level.destroyBlockProgress(this.player.getId(), blockposition, -1);
152 + this.player.connection.send(new PacketPlayOutBlockBreak(blockposition, this.level.getBlockState(blockposition), packetplayinblockdig_enumplayerdigtype, true, "aborted destroying"));
153 ++
154 ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, blockposition, this.player.getInventory().getSelected()); // CraftBukkit
155 + }
156 +
157 + }
158 +@@ -224,17 +308,72 @@
150 159 if (this.destroyBlock(blockposition)) {
151 160 this.player.connection.send(new PacketPlayOutBlockBreak(blockposition, this.level.getBlockState(blockposition), packetplayinblockdig_enumplayerdigtype, true, s));
152 161 } else {
153 162 - this.player.connection.send(new PacketPlayOutBlockBreak(blockposition, this.level.getBlockState(blockposition), packetplayinblockdig_enumplayerdigtype, false, s));
154 163 + this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); // CraftBukkit - SPIGOT-5196
155 164 }
156 165
157 166 }
158 167
159 168 public boolean destroyBlock(BlockPosition blockposition) {
170 179 + // Don't tell the client if its a creative sword break because its not broken!
171 180 + if (level.getBlockEntity(blockposition) == null && !isSwordNoBreak) {
172 181 + PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(blockposition, Blocks.AIR.defaultBlockState());
173 182 + this.player.connection.send(packet);
174 183 + }
175 184 +
176 185 + event = new BlockBreakEvent(bblock, this.player.getBukkitEntity());
177 186 +
178 187 + // Sword + Creative mode pre-cancel
179 188 + event.setCancelled(isSwordNoBreak);
180 -+
189 +
190 +- if (!this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player)) {
181 191 + // Calculate default block experience
182 192 + IBlockData nmsData = this.level.getBlockState(blockposition);
183 193 + Block nmsBlock = nmsData.getBlock();
184 194 +
185 195 + ItemStack itemstack = this.player.getItemBySlot(EnumItemSlot.MAINHAND);
186 196 +
187 197 + if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) {
188 198 + event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, blockposition, itemstack));
189 199 + }
190 200 +
194 204 + if (isSwordNoBreak) {
195 205 + return false;
196 206 + }
197 207 + // Let the client know the block still exists
198 208 + this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition));
199 209 +
200 210 + // Brute force all possible updates
201 211 + for (EnumDirection dir : EnumDirection.values()) {
202 212 + this.player.connection.send(new PacketPlayOutBlockChange(level, blockposition.relative(dir)));
203 213 + }
204 -
205 -- if (!this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player)) {
214 ++
206 215 + // Update any tile entity data for this block
207 216 + TileEntity tileentity = this.level.getBlockEntity(blockposition);
208 217 + if (tileentity != null) {
209 218 + this.player.connection.send(tileentity.getUpdatePacket());
210 219 + }
211 220 + return false;
212 221 + }
213 222 + }
214 223 + // CraftBukkit end
215 224 +
216 225 + if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player)) { // CraftBukkit - false
217 226 return false;
218 227 } else {
219 228 + iblockdata = this.level.getBlockState(blockposition); // CraftBukkit - update state from plugins
220 229 + if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling
221 230 TileEntity tileentity = this.level.getBlockEntity(blockposition);
222 231 Block block = iblockdata.getBlock();
223 232
224 -@@ -244,6 +381,10 @@
233 +@@ -244,6 +383,10 @@
225 234 } else if (this.player.blockActionRestricted(this.level, blockposition, this.gameModeForPlayer)) {
226 235 return false;
227 236 } else {
228 237 + // CraftBukkit start
229 238 + org.bukkit.block.BlockState state = bblock.getState();
230 239 + level.captureDrops = new ArrayList<>();
231 240 + // CraftBukkit end
232 241 block.playerWillDestroy(this.level, blockposition, iblockdata, this.player);
233 242 boolean flag = this.level.removeBlock(blockposition, false);
234 243
235 -@@ -252,19 +393,32 @@
244 +@@ -252,19 +395,32 @@
236 245 }
237 246
238 247 if (this.isCreative()) {
239 248 - return true;
240 249 + // return true; // CraftBukkit
241 250 } else {
242 251 ItemStack itemstack = this.player.getMainHandItem();
243 252 ItemStack itemstack1 = itemstack.copy();
244 253 boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata);
245 254
261 270 + // Drop event experience
262 271 + if (flag && event != null) {
263 272 + iblockdata.getBlock().popExperience(this.level, blockposition, event.getExpToDrop());
264 273 }
265 274 +
266 275 + return true;
267 276 + // CraftBukkit end
268 277 }
269 278 }
270 279 }
271 -@@ -306,12 +460,52 @@
280 +@@ -306,12 +462,52 @@
272 281 }
273 282 }
274 283
275 284 + // CraftBukkit start - whole method
276 285 + public boolean interactResult = false;
277 286 + public boolean firedInteract = false;
278 287 + public BlockPosition interactPosition;
279 288 + public EnumHand interactHand;
280 289 + public ItemStack interactItemStack;
281 290 public EnumInteractionResult useItemOn(EntityPlayer entityplayer, World world, ItemStack itemstack, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) {
314 323 + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc)
315 324 + entityplayer.connection.send(new PacketPlayOutBlockChange(world, blockposition.above()));
316 325 + }
317 326 + entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867
318 327 + enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS;
319 328 + } else if (this.gameModeForPlayer == EnumGamemode.SPECTATOR) {
320 329 + ITileInventory itileinventory = iblockdata.getMenuProvider(world, blockposition);
321 330
322 331 if (itileinventory != null) {
323 332 entityplayer.openMenu(itileinventory);
324 -@@ -325,7 +519,7 @@
333 +@@ -325,7 +521,7 @@
325 334 ItemStack itemstack1 = itemstack.copy();
326 335
327 336 if (!flag1) {
328 337 - EnumInteractionResult enuminteractionresult = iblockdata.use(world, entityplayer, enumhand, movingobjectpositionblock);
329 338 + enuminteractionresult = iblockdata.use(world, entityplayer, enumhand, movingobjectpositionblock);
330 339
331 340 if (enuminteractionresult.consumesAction()) {
332 341 CriterionTriggers.ITEM_USED_ON_BLOCK.trigger(entityplayer, blockposition, itemstack1);
333 -@@ -333,17 +527,17 @@
342 +@@ -333,17 +529,17 @@
334 343 }
335 344 }
336 345
337 346 - if (!itemstack.isEmpty() && !entityplayer.getCooldowns().isOnCooldown(itemstack.getItem())) {
338 347 + if (!itemstack.isEmpty() && enuminteractionresult != EnumInteractionResult.SUCCESS && !interactResult) { // add !interactResult SPIGOT-764
339 348 ItemActionContext itemactioncontext = new ItemActionContext(entityplayer, enumhand, movingobjectpositionblock);
340 349 EnumInteractionResult enuminteractionresult1;
341 350
342 351 if (this.isCreative()) {
343 352 int i = itemstack.getCount();
344 353
345 354 - enuminteractionresult1 = itemstack.useOn(itemactioncontext);
346 355 + enuminteractionresult1 = itemstack.useOn(itemactioncontext, enumhand);
347 356 itemstack.setCount(i);
348 357 } else {
349 358 - enuminteractionresult1 = itemstack.useOn(itemactioncontext);
350 359 + enuminteractionresult1 = itemstack.useOn(itemactioncontext, enumhand);
351 360 }
352 361
353 362 if (enuminteractionresult1.consumesAction()) {
354 -@@ -351,10 +545,10 @@
363 +@@ -351,10 +547,10 @@
355 364 }
356 365
357 366 return enuminteractionresult1;
358 367 - } else {
359 368 - return EnumInteractionResult.PASS;
360 369 }
361 370 }
362 371 + return enuminteractionresult;
363 372 + // CraftBukkit end
364 373 }

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut