Commits
1 - | --- /home/matt/mc-dev-private//net/minecraft/server/PlayerConnection.java 2015-04-14 10:14:05.807811715 +0100 |
2 - | +++ src/main/java/net/minecraft/server/PlayerConnection.java 2015-04-14 10:14:05.811811715 +0100 |
1 + | --- /home/matt/mc-dev-private//net/minecraft/server/PlayerConnection.java 2015-04-15 16:24:44.436922448 +0100 |
2 + | +++ src/main/java/net/minecraft/server/PlayerConnection.java 2015-04-15 16:24:44.440922447 +0100 |
3 3 | |
4 4 | import org.apache.logging.log4j.LogManager; |
5 5 | import org.apache.logging.log4j.Logger; |
6 6 | |
7 7 | +// CraftBukkit start |
8 8 | +import java.util.concurrent.ExecutionException; |
9 9 | +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; |
10 10 | +import java.util.HashSet; |
11 11 | + |
12 12 | +import org.bukkit.craftbukkit.entity.CraftPlayer; |
109 109 | + for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; |
110 110 | + /* Use thread-safe field access instead |
111 111 | if (this.chatThrottle > 0) { |
112 112 | --this.chatThrottle; |
113 113 | } |
114 114 | + */ |
115 115 | + // CraftBukkit end |
116 116 | |
117 117 | if (this.m > 0) { |
118 118 | --this.m; |
119 - | |
119 + | |
120 120 | } |
121 121 | |
122 122 | public void disconnect(String s) { |
123 123 | + // CraftBukkit start - fire PlayerKickEvent |
124 124 | + String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; |
125 125 | + |
126 126 | + PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); |
127 127 | + |
128 128 | + if (this.server.getServer().isRunning()) { |
129 129 | + this.server.getPluginManager().callEvent(event); |
140 140 | |
141 141 | this.networkManager.a(new PacketPlayOutKickDisconnect(chatcomponenttext), new GenericFutureListener() { |
142 142 | - public void operationComplete(Future<? super Void> future) throws Exception { |
143 143 | + public void operationComplete(Future future) throws Exception { // CraftBukkit - fix decompile error |
144 144 | PlayerConnection.this.networkManager.close(chatcomponenttext); |
145 145 | } |
146 146 | }, new GenericFutureListener[0]); |
147 147 | + this.a(chatcomponenttext); // CraftBukkit - fire quit instantly |
148 148 | this.networkManager.k(); |
149 149 | - Futures.getUnchecked(this.minecraftServer.postToMainThread(new Runnable() { |
150 - | + // CraftBukkit - Don't wait |
151 - | + this.minecraftServer.postToMainThread(new Runnable() { |
152 - | public void run() { |
153 - | PlayerConnection.this.networkManager.l(); |
154 - | } |
150 + | - public void run() { |
151 + | - PlayerConnection.this.networkManager.l(); |
152 + | - } |
155 153 | - })); |
156 - | + }); |
157 154 | } |
158 155 | |
159 156 | public void a(PacketPlayInSteerVehicle packetplayinsteervehicle) { |
160 - | |
157 + | |
161 158 | |
162 159 | public void a(PacketPlayInFlying packetplayinflying) { |
163 160 | PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.u()); |
164 161 | + // CraftBukkit start - Check for NaN |
165 162 | + if (!NumberConversions.isFinite(packetplayinflying.x) |
166 163 | + || !NumberConversions.isFinite(packetplayinflying.y) |
167 164 | + || !NumberConversions.isFinite(packetplayinflying.z) |
168 165 | + || !NumberConversions.isFinite(packetplayinflying.yaw) |
169 166 | + || !NumberConversions.isFinite(packetplayinflying.pitch)) { |
170 167 | + c.warn(player.getName() + " was caught trying to crash the server with an invalid position."); |
171 168 | + getPlayer().kickPlayer("Nope!"); |
172 169 | + return; |
173 170 | + } |
174 171 | + // CraftBukkit end |
175 172 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
176 173 | |
177 174 | this.h = true; |
178 - | |
175 + | |
179 176 | this.checkMovement = true; |
180 177 | } |
181 178 | } |
182 179 | + // CraftBukkit start - fire PlayerMoveEvent |
183 180 | + Player player = this.getPlayer(); |
184 181 | + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. |
185 182 | + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. |
186 183 | + |
187 184 | + // If the packet contains movement information then we update the To location with the correct XYZ. |
188 185 | + if (packetplayinflying.hasPos && !(packetplayinflying.hasPos && packetplayinflying.y == -999.0D)) { |
212 209 | + if (from.getX() != Double.MAX_VALUE) { |
213 210 | + Location oldTo = to.clone(); |
214 211 | + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); |
215 212 | + this.server.getPluginManager().callEvent(event); |
216 213 | + |
217 214 | + // If the event is cancelled we move the player back to their old location. |
218 215 | + if (event.isCancelled()) { |
219 216 | + this.player.playerConnection.sendPacket(new PacketPlayOutPosition(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.<PacketPlayOutPosition.EnumPlayerTeleportFlags>emptySet())); |
220 217 | + return; |
221 218 | + } |
222 - | + |
219 + | |
220 + | - if (this.checkMovement) { |
223 221 | + /* If a Plugin has changed the To destination then we teleport the Player |
224 222 | + there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. |
225 223 | + We only do this if the Event was not cancelled. */ |
226 224 | + if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { |
227 225 | + this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.UNKNOWN); |
228 226 | + return; |
229 227 | + } |
230 - | |
231 - | - if (this.checkMovement) { |
228 + | + |
232 229 | + /* Check to see if the Players Location has some how changed during the call of the event. |
233 230 | + This can happen due to a plugin teleporting the player instead of using .setTo() */ |
234 231 | + if (!from.equals(this.getPlayer().getLocation()) && this.justTeleported) { |
235 232 | + this.justTeleported = false; |
236 233 | + return; |
237 234 | + } |
238 235 | + } |
239 236 | + } |
240 237 | + |
241 238 | + if (this.checkMovement && !this.player.dead) { |
242 239 | + // CraftBukkit end |
243 240 | this.f = this.e; |
244 241 | double d7; |
245 242 | double d8; |
246 - | |
243 + | |
247 244 | double d11 = d7 - this.player.locX; |
248 245 | double d12 = d8 - this.player.locY; |
249 246 | double d13 = d9 - this.player.locZ; |
250 247 | - double d14 = Math.min(Math.abs(d11), Math.abs(this.player.motX)); |
251 248 | - double d15 = Math.min(Math.abs(d12), Math.abs(this.player.motY)); |
252 249 | - double d16 = Math.min(Math.abs(d13), Math.abs(this.player.motZ)); |
253 250 | + // CraftBukkit start - min to max |
254 251 | + double d14 = Math.max(Math.abs(d11), Math.abs(this.player.motX)); |
255 252 | + double d15 = Math.max(Math.abs(d12), Math.abs(this.player.motY)); |
256 253 | + double d16 = Math.max(Math.abs(d13), Math.abs(this.player.motZ)); |
257 254 | + // CraftBukkit end |
258 255 | double d17 = d14 * d14 + d15 * d15 + d16 * d16; |
259 256 | |
260 257 | - if (d17 > 100.0D && (!this.minecraftServer.S() || !this.minecraftServer.R().equals(this.player.getName()))) { |
261 258 | + if (d17 > 100.0D && this.checkMovement && (!this.minecraftServer.S() || !this.minecraftServer.R().equals(this.player.getName()))) { // CraftBukkit - Added this.checkMovement condition to solve this check being triggered by teleports |
262 259 | PlayerConnection.c.warn(this.player.getName() + " moved too quickly! " + d11 + "," + d12 + "," + d13 + " (" + d14 + ", " + d15 + ", " + d16 + ")"); |
263 260 | this.a(this.o, this.p, this.q, this.player.yaw, this.player.pitch); |
264 261 | return; |
265 - | |
262 + | |
266 263 | } |
267 264 | |
268 265 | public void a(double d0, double d1, double d2, float f, float f1) { |
269 266 | - this.a(d0, d1, d2, f, f1, Collections.emptySet()); |
270 267 | + this.a(d0, d1, d2, f, f1, Collections.<PacketPlayOutPosition.EnumPlayerTeleportFlags>emptySet()); // CraftBukkit fix decompile errors |
271 268 | } |
272 269 | |
273 270 | public void a(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set) { |
274 271 | + // CraftBukkit start - Delegate to teleport(Location) |
275 272 | + Player player = this.getPlayer(); |
310 307 | + this.lastPosX = d0; |
311 308 | + this.lastPosY = d1; |
312 309 | + this.lastPosZ = d2; |
313 310 | + this.lastYaw = f; |
314 311 | + this.lastPitch = f1; |
315 312 | + this.justTeleported = true; |
316 313 | + // CraftBukkit end |
317 314 | this.checkMovement = false; |
318 315 | this.o = d0; |
319 316 | this.p = d1; |
320 - | |
317 + | |
321 318 | |
322 319 | public void a(PacketPlayInBlockDig packetplayinblockdig) { |
323 320 | PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.u()); |
324 321 | + if (this.player.dead) return; // CraftBukkit |
325 322 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
326 323 | BlockPosition blockposition = packetplayinblockdig.a(); |
327 324 | |
328 325 | this.player.z(); |
329 326 | + // CraftBukkit start |
330 327 | switch (PlayerConnection.SyntheticClass_1.a[packetplayinblockdig.c().ordinal()]) { |
366 363 | |
367 364 | - case 4: |
368 365 | - case 5: |
369 366 | - case 6: |
370 367 | + case 4: // START_DESTROY_BLOCK |
371 368 | + case 5: // ABORT_DESTROY_BLOCK |
372 369 | + case 6: // STOP_DESTROY_BLOCK |
373 370 | double d0 = this.player.locX - ((double) blockposition.getX() + 0.5D); |
374 371 | double d1 = this.player.locY - ((double) blockposition.getY() + 0.5D) + 1.5D; |
375 372 | double d2 = this.player.locZ - ((double) blockposition.getZ() + 0.5D); |
376 - | |
373 + | |
377 374 | if (!this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) { |
378 375 | this.player.playerInteractManager.a(blockposition, packetplayinblockdig.b()); |
379 376 | } else { |
380 377 | + // CraftBukkit start - fire PlayerInteractEvent |
381 378 | + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, packetplayinblockdig.b(), this.player.inventory.getItemInHand()); |
382 379 | this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); |
383 380 | + // Update any tile entity data for this block |
384 381 | + TileEntity tileentity = worldserver.getTileEntity(blockposition); |
385 382 | + if (tileentity != null) { |
386 383 | + this.player.playerConnection.sendPacket(tileentity.getUpdatePacket()); |
387 384 | + } |
388 385 | + // CraftBukkit end |
389 386 | } |
390 387 | } else { |
391 388 | if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { |
392 - | |
389 + | |
393 390 | default: |
394 391 | throw new IllegalArgumentException("Invalid player action"); |
395 392 | } |
396 393 | + // CraftBukkit end |
397 394 | } |
398 395 | |
399 396 | public void a(PacketPlayInBlockPlace packetplayinblockplace) { |
400 397 | PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.u()); |
401 398 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
402 399 | + |
405 402 | + |
406 403 | + // CraftBukkit - if rightclick decremented the item, always send the update packet. */ |
407 404 | + // this is not here for CraftBukkit's own functionality; rather it is to fix |
408 405 | + // a notch bug where the item doesn't update correctly. |
409 406 | + boolean always = false; |
410 407 | + // CraftBukkit end |
411 408 | + |
412 409 | ItemStack itemstack = this.player.inventory.getItemInHand(); |
413 410 | boolean flag = false; |
414 411 | BlockPosition blockposition = packetplayinblockplace.a(); |
415 - | |
412 + | |
416 413 | return; |
417 414 | } |
418 415 | |
419 416 | - this.player.playerInteractManager.useItem(this.player, worldserver, itemstack); |
420 417 | + // CraftBukkit start |
421 418 | + int itemstackAmount = itemstack.count; |
422 419 | + |
423 420 | + // Raytrace to look for 'rogue armswings' |
424 421 | + float f1 = this.player.pitch; |
425 422 | + float f2 = this.player.yaw; |
457 454 | + } |
458 455 | + |
459 456 | + // CraftBukkit - notch decrements the counter by 1 in the above method with food, |
460 457 | + // snowballs and so forth, but he does it in a place that doesn't cause the |
461 458 | + // inventory update packet to get sent |
462 459 | + always = (itemstack.count != itemstackAmount) || itemstack.getItem() == Item.getItemOf(Blocks.WATERLILY); |
463 460 | + // CraftBukkit end |
464 461 | } else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight() - 1 && (enumdirection == EnumDirection.UP || blockposition.getY() >= this.minecraftServer.getMaxBuildHeight())) { |
465 462 | ChatMessage chatmessage = new ChatMessage("build.tooHigh", new Object[] { Integer.valueOf(this.minecraftServer.getMaxBuildHeight())}); |
466 463 | |
467 - | |
464 + | |
468 465 | this.player.playerConnection.sendPacket(new PacketPlayOutChat(chatmessage)); |
469 466 | flag = true; |
470 467 | } else { |
471 468 | + // CraftBukkit start - Check if we can actually do something over this large a distance |
472 469 | + Location eyeLoc = this.getPlayer().getEyeLocation(); |
473 470 | + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); |
474 471 | + if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { |
475 472 | + return; |
476 473 | + } |
477 474 | + |
478 475 | + if (!worldserver.getWorldBorder().a(blockposition)) { |
479 476 | + return; |
480 477 | + } |
481 478 | + |
482 479 | if (this.checkMovement && this.player.e((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && !this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) { |
483 480 | - this.player.playerInteractManager.interact(this.player, worldserver, itemstack, blockposition, enumdirection, packetplayinblockplace.d(), packetplayinblockplace.e(), packetplayinblockplace.f()); |
484 481 | + always = !this.player.playerInteractManager.interact(this.player, worldserver, itemstack, blockposition, enumdirection, packetplayinblockplace.d(), packetplayinblockplace.e(), packetplayinblockplace.f()); |
485 482 | } |
486 483 | |
487 484 | flag = true; |
488 - | |
485 + | |
489 486 | |
490 487 | this.player.activeContainer.b(); |
491 488 | this.player.g = false; |
492 489 | - if (!ItemStack.matches(this.player.inventory.getItemInHand(), packetplayinblockplace.getItemStack())) { |
493 490 | + // CraftBukkit - TODO CHECK IF NEEDED -- new if structure might not need 'always'. Kept it in for now, but may be able to remove in future |
494 491 | + if (!ItemStack.matches(this.player.inventory.getItemInHand(), packetplayinblockplace.getItemStack()) || always) { |
495 492 | this.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, slot.rawSlotIndex, this.player.inventory.getItemInHand())); |
496 493 | } |
497 494 | } |
498 - | |
495 + | |
499 496 | WorldServer[] aworldserver = this.minecraftServer.worldServer; |
500 497 | int i = aworldserver.length; |
501 498 | |
502 499 | - for (int j = 0; j < i; ++j) { |
503 500 | - WorldServer worldserver = aworldserver[j]; |
504 501 | + // CraftBukkit - use the worlds array list |
505 502 | + for (WorldServer worldserver : minecraftServer.worlds) { |
506 503 | |
507 504 | if (worldserver != null) { |
508 505 | entity = packetplayinspectate.a(worldserver); |
509 - | |
506 + | |
510 507 | if (entity != null) { |
511 508 | this.player.e((Entity) this.player); |
512 509 | this.player.mount((Entity) null); |
513 510 | + |
514 511 | + /* CraftBukkit start - replace with bukkit handling for multi-world |
515 512 | if (entity.world != this.player.world) { |
516 513 | WorldServer worldserver1 = this.player.u(); |
517 514 | WorldServer worldserver2 = (WorldServer) entity.world; |
518 - | |
515 + | |
519 516 | } else { |
520 517 | this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ); |
521 518 | } |
522 519 | + */ |
523 520 | + this.player.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE); |
524 521 | + // CraftBukkit end |
525 522 | } |
526 523 | } |
527 524 | |
528 - | |
525 + | |
529 526 | public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) {} |
530 527 | |
531 528 | public void a(IChatBaseComponent ichatbasecomponent) { |
532 529 | - PlayerConnection.c.info(this.player.getName() + " lost connection: " + ichatbasecomponent); |
533 530 | + // CraftBukkit start - Rarely it would send a disconnect line twice |
534 531 | + if (this.processedDisconnect) { |
535 532 | + return; |
536 533 | + } else { |
537 534 | + this.processedDisconnect = true; |
538 535 | + } |
550 547 | this.player.q(); |
551 548 | - this.minecraftServer.getPlayerList().disconnect(this.player); |
552 549 | + String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); |
553 550 | + if ((quitMessage != null) && (quitMessage.length() > 0)) { |
554 551 | + this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); |
555 552 | + } |
556 553 | + // CraftBukkit end |
557 554 | if (this.minecraftServer.S() && this.player.getName().equals(this.minecraftServer.R())) { |
558 555 | PlayerConnection.c.info("Stopping singleplayer server as player logged out"); |
559 556 | this.minecraftServer.safeShutdown(); |
560 - | |
557 + | |
561 558 | } |
562 559 | } |
563 560 | |
564 561 | + // CraftBukkit start |
565 562 | + if (packet == null) { |
566 563 | + return; |
567 564 | + } else if (packet instanceof PacketPlayOutSpawnPosition) { |
568 565 | + PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet; |
569 566 | + this.player.compassTarget = new Location(this.getPlayer().getWorld(), packet6.position.getX(), packet6.position.getY(), packet6.position.getZ()); |
570 567 | + } |
571 568 | + // CraftBukkit end |
572 569 | + |
573 570 | try { |
574 571 | this.networkManager.handle(packet); |
575 572 | } catch (Throwable throwable) { |
576 - | |
573 + | |
577 574 | } |
578 575 | |
579 576 | public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) { |
580 577 | + // CraftBukkit start |
581 578 | + if (this.player.dead) return; |
582 579 | PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.u()); |
583 580 | if (packetplayinhelditemslot.a() >= 0 && packetplayinhelditemslot.a() < PlayerInventory.getHotbarSize()) { |
584 581 | + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.a()); |
585 582 | + this.server.getPluginManager().callEvent(event); |
586 583 | + if (event.isCancelled()) { |
603 600 | + // CraftBukkit start - async chat |
604 601 | + boolean isSync = packetplayinchat.a().startsWith("/"); |
605 602 | + if (packetplayinchat.a().startsWith("/")) { |
606 603 | + PlayerConnectionUtils.ensureMainThread(packetplayinchat, this, this.player.u()); |
607 604 | + } |
608 605 | + // CraftBukkit end |
609 606 | + if (this.player.dead || this.player.getChatFlags() == EntityHuman.EnumChatVisibility.HIDDEN) { // CraftBukkit - dead men tell no tales |
610 607 | ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]); |
611 608 | |
612 609 | chatmessage.getChatModifier().setColor(EnumChatFormat.RED); |
613 - | |
610 + | |
614 611 | |
615 612 | for (int i = 0; i < s.length(); ++i) { |
616 613 | if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) { |
617 614 | - this.disconnect("Illegal characters in chat"); |
618 615 | + // CraftBukkit start - threadsafety |
619 616 | + if (!isSync) { |
620 617 | + Waitable waitable = new Waitable() { |
621 618 | + @Override |
622 619 | + protected Object evaluate() { |
623 620 | + PlayerConnection.this.disconnect("Illegal characters in chat"); |
861 858 | + |
862 859 | + if (e2.isCancelled()) { |
863 860 | + return; |
864 861 | + } |
865 862 | + break; |
866 863 | + } |
867 864 | + // CraftBukkit end |
868 865 | this.player.z(); |
869 866 | switch (PlayerConnection.SyntheticClass_1.b[packetplayinentityaction.b().ordinal()]) { |
870 867 | case 1: |
871 - | |
868 + | |
872 869 | |
873 870 | case 5: |
874 871 | this.player.a(false, true, true); |
875 872 | - this.checkMovement = false; |
876 873 | + // this.checkMovement = false; // CraftBukkit - this is handled in teleport |
877 874 | break; |
878 875 | |
879 876 | case 6: |
880 - | |
877 + | |
881 878 | } |
882 879 | |
883 880 | public void a(PacketPlayInUseEntity packetplayinuseentity) { |
884 881 | + if (this.player.dead) return; // CraftBukkit |
885 882 | PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.u()); |
886 883 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
887 884 | Entity entity = packetplayinuseentity.a((World) worldserver); |
888 - | |
885 + | |
889 886 | } |
890 887 | |
891 888 | if (this.player.h(entity) < d0) { |
892 889 | + ItemStack itemInHand = this.player.inventory.getItemInHand(); // CraftBukkit |
893 890 | + |
894 891 | + if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT |
895 892 | + || packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { |
896 893 | + // CraftBukkit start |
897 894 | + boolean triggerTagUpdate = itemInHand != null && itemInHand.getItem() == Items.NAME_TAG && entity instanceof EntityInsentient; |
898 895 | + boolean triggerChestUpdate = itemInHand != null && itemInHand.getItem() == Item.getItemOf(Blocks.CHEST) && entity instanceof EntityHorse; |
951 948 | this.player.attack(entity); |
952 949 | + |
953 950 | + // CraftBukkit start |
954 951 | + if (itemInHand != null && itemInHand.count <= -1) { |
955 952 | + this.player.updateInventory(this.player.activeContainer); |
956 953 | + } |
957 954 | + // CraftBukkit end |
958 955 | } |
959 956 | } |
960 957 | } |
961 - | |
958 + | |
962 959 | switch (PlayerConnection.SyntheticClass_1.c[packetplayinclientcommand_enumclientcommand.ordinal()]) { |
963 960 | case 1: |
964 961 | if (this.player.viewingCredits) { |
965 962 | - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true); |
966 963 | + // this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true); |
967 964 | + this.minecraftServer.getPlayerList().changeDimension(this.player, 0, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management |
968 965 | } else if (this.player.u().getWorldData().isHardcore()) { |
969 966 | if (this.minecraftServer.S() && this.player.getName().equals(this.minecraftServer.R())) { |
970 967 | this.player.playerConnection.disconnect("You have died. Game over, man, it\'s game over!"); |
971 - | |
968 + | |
972 969 | } |
973 970 | |
974 971 | public void a(PacketPlayInCloseWindow packetplayinclosewindow) { |
975 972 | + if (this.player.dead) return; // CraftBukkit |
976 973 | PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.u()); |
977 974 | + |
978 975 | + CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit |
979 976 | + |
980 977 | this.player.p(); |
981 978 | } |
984 981 | + if (this.player.dead) return; // CraftBukkit |
985 982 | PlayerConnectionUtils.ensureMainThread(packetplayinwindowclick, this, this.player.u()); |
986 983 | this.player.z(); |
987 984 | if (this.player.activeContainer.windowId == packetplayinwindowclick.a() && this.player.activeContainer.c(this.player)) { |
988 985 | - if (this.player.v()) { |
989 986 | + boolean cancelled = this.player.v(); // CraftBukkit - see below if |
990 987 | + if (false) { // CraftBukkit this.player.v()) { |
991 988 | ArrayList arraylist = Lists.newArrayList(); |
992 989 | |
993 990 | for (int i = 0; i < this.player.activeContainer.c.size(); ++i) { |
994 - | |
991 + | |
995 992 | |
996 993 | this.player.a(this.player.activeContainer, (List) arraylist); |
997 994 | } else { |
998 995 | - ItemStack itemstack = this.player.activeContainer.clickItem(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player); |
999 996 | + // ItemStack itemstack = this.player.activeContainer.clickItem(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player); |
1000 997 | + // CraftBukkit start - Call InventoryClickEvent |
1001 998 | + if (packetplayinwindowclick.b() < -1 && packetplayinwindowclick.b() != -999) { |
1002 999 | + return; |
1003 1000 | + } |
1004 1001 | + |
1256 1253 | + if (event instanceof CraftItemEvent) { |
1257 1254 | + // Need to update the inventory on crafting to |
1258 1255 | + // correctly support custom recipes |
1259 1256 | + player.updateInventory(player.activeContainer); |
1260 1257 | + } |
1261 1258 | + } |
1262 1259 | + // CraftBukkit end |
1263 1260 | |
1264 1261 | if (ItemStack.matches(packetplayinwindowclick.e(), itemstack)) { |
1265 1262 | this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), true)); |
1266 - | |
1263 + | |
1267 1264 | } |
1268 1265 | |
1269 1266 | boolean flag1 = packetplayinsetcreativeslot.a() >= 1 && packetplayinsetcreativeslot.a() < 36 + PlayerInventory.getHotbarSize(); |
1270 1267 | - boolean flag2 = itemstack == null || itemstack.getItem() != null; |
1271 1268 | + // CraftBukkit - Add invalidItems check |
1272 1269 | + boolean flag2 = itemstack == null || itemstack.getItem() != null && !invalidItems.contains(Item.getId(itemstack.getItem())); |
1273 1270 | boolean flag3 = itemstack == null || itemstack.getData() >= 0 && itemstack.count <= 64 && itemstack.count > 0; |
1274 1271 | + // CraftBukkit start - Call click event |
1275 1272 | + if (flag || (flag1 && !ItemStack.matches(this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem(), packetplayinsetcreativeslot.getItemStack()))) { // Insist on valid slot |
1276 1273 | + |
1306 1303 | + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.defaultContainer.windowId, packetplayinsetcreativeslot.a(), this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem())); |
1307 1304 | + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, null)); |
1308 1305 | + } |
1309 1306 | + return; |
1310 1307 | + } |
1311 1308 | + } |
1312 1309 | + // CraftBukkit end |
1313 1310 | |
1314 1311 | if (flag1 && flag2 && flag3) { |
1315 1312 | if (itemstack == null) { |
1316 - | |
1313 + | |
1317 1314 | } |
1318 1315 | |
1319 1316 | public void a(PacketPlayInTransaction packetplayintransaction) { |
1320 1317 | + if (this.player.dead) return; // CraftBukkit |
1321 1318 | PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.u()); |
1322 1319 | Short oshort = (Short) this.n.get(this.player.activeContainer.windowId); |
1323 1320 | |
1324 - | |
1321 + | |
1325 1322 | } |
1326 1323 | |
1327 1324 | public void a(PacketPlayInUpdateSign packetplayinupdatesign) { |
1328 1325 | + if (this.player.dead) return; // CraftBukkit |
1329 1326 | PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.u()); |
1330 1327 | this.player.z(); |
1331 1328 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
1332 - | |
1329 + | |
1333 1330 | |
1334 1331 | if (!tileentitysign.b() || tileentitysign.c() != this.player) { |
1335 1332 | this.minecraftServer.warning("Player " + this.player.getName() + " just tried to change non-editable sign"); |
1336 1333 | + this.sendPacket(new PacketPlayOutUpdateSign(tileentity.world, packetplayinupdatesign.a(), tileentitysign.lines)); // CraftBukkit |
1337 1334 | return; |
1338 1335 | } |
1339 1336 | |
1340 1337 | IChatBaseComponent[] aichatbasecomponent = packetplayinupdatesign.b(); |
1341 1338 | |
1342 1339 | + // CraftBukkit start |
1354 1351 | + |
1355 1352 | + if (!event.isCancelled()) { |
1356 1353 | + System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); |
1357 1354 | + tileentitysign.isEditable = false; |
1358 1355 | } |
1359 1356 | + // System.arraycopy(packetplayinupdatesign.b(), 0, tileentitysign.lines, 0, 4); |
1360 1357 | + // CraftBukkit end |
1361 1358 | |
1362 1359 | tileentitysign.update(); |
1363 1360 | worldserver.notify(blockposition); |
1364 - | |
1361 + | |
1365 1362 | |
1366 1363 | public void a(PacketPlayInAbilities packetplayinabilities) { |
1367 1364 | PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.u()); |
1368 1365 | - this.player.abilities.isFlying = packetplayinabilities.isFlying() && this.player.abilities.canFly; |
1369 1366 | + // CraftBukkit start |
1370 1367 | + if (this.player.abilities.canFly && this.player.abilities.isFlying != packetplayinabilities.isFlying()) { |
1371 1368 | + PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.server.getPlayer(this.player), packetplayinabilities.isFlying()); |
1372 1369 | + this.server.getPluginManager().callEvent(event); |
1373 1370 | + if (!event.isCancelled()) { |
1374 1371 | + this.player.abilities.isFlying = packetplayinabilities.isFlying(); // Actually set the player's flying status |
1383 1380 | PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.u()); |
1384 1381 | + // CraftBukkit start |
1385 1382 | + if (chatSpamField.addAndGet(this, 10) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { |
1386 1383 | + this.disconnect("disconnect.spam"); |
1387 1384 | + return; |
1388 1385 | + } |
1389 1386 | + // CraftBukkit end |
1390 1387 | ArrayList arraylist = Lists.newArrayList(); |
1391 1388 | Iterator iterator = this.minecraftServer.tabCompleteCommand(this.player, packetplayintabcomplete.a(), packetplayintabcomplete.b()).iterator(); |
1392 1389 | |
1393 - | |
1390 + | |
1394 1391 | itemstack1 = this.player.inventory.getItemInHand(); |
1395 1392 | if (itemstack1 != null) { |
1396 1393 | if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack.getItem() == itemstack1.getItem()) { |
1397 1394 | + itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit |
1398 1395 | itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); |
1399 1396 | + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit |
1400 1397 | } |
1401 1398 | |
1402 1399 | return; |
1403 1400 | } |
1404 1401 | } catch (Exception exception) { |
1405 1402 | PlayerConnection.c.error("Couldn\'t handle book info", exception); |
1406 1403 | + this.disconnect("Invalid book data!"); // CraftBukkit |
1407 1404 | return; |
1408 1405 | } finally { |
1409 1406 | packetdataserializer.release(); |
1410 - | |
1407 + | |
1411 1408 | itemstack1 = this.player.inventory.getItemInHand(); |
1412 1409 | if (itemstack1 != null) { |
1413 1410 | if (itemstack.getItem() == Items.WRITTEN_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) { |
1414 1411 | + // CraftBukkit start |
1415 1412 | + itemstack1 = new ItemStack(Items.WRITTEN_BOOK); |
1416 1413 | itemstack1.a("author", (NBTBase) (new NBTTagString(this.player.getName()))); |
1417 1414 | itemstack1.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title")))); |
1418 1415 | itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); |
1419 1416 | itemstack1.setItem(Items.WRITTEN_BOOK); |
1420 1417 | + CraftEventFactory.handleEditBookEvent(player, itemstack1); |
1421 1418 | + // CraftBukkit end |
1422 1419 | } |
1423 1420 | |
1424 1421 | return; |
1425 1422 | } |
1426 1423 | } catch (Exception exception1) { |
1427 1424 | PlayerConnection.c.error("Couldn\'t sign book", exception1); |
1428 1425 | + this.disconnect("Invalid book data!"); // CraftBukkit |
1429 1426 | return; |
1430 1427 | } finally { |
1431 1428 | packetdataserializer.release(); |
1432 - | |
1429 + | |
1433 1430 | } |
1434 1431 | } catch (Exception exception2) { |
1435 1432 | PlayerConnection.c.error("Couldn\'t select trade", exception2); |
1436 1433 | + this.disconnect("Invalid trade data!"); // CraftBukkit |
1437 1434 | } |
1438 1435 | } else if ("MC|AdvCdm".equals(packetplayincustompayload.a())) { |
1439 1436 | if (!this.minecraftServer.getEnableCommandBlock()) { |
1440 1437 | this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0])); |
1441 1438 | - } else if (this.player.a(2, "") && this.player.abilities.canInstantlyBuild) { |
1442 1439 | + } else if (this.player.getBukkitEntity().isOp() && this.player.abilities.canInstantlyBuild) { // CraftBukkit - Change to Bukkit OP versus Vanilla OP |
1443 1440 | packetdataserializer = packetplayincustompayload.b(); |
1444 1441 | |
1445 1442 | try { |
1446 - | |
1443 + | |
1447 1444 | } |
1448 1445 | } catch (Exception exception3) { |
1449 1446 | PlayerConnection.c.error("Couldn\'t set command block", exception3); |
1450 1447 | + this.disconnect("Invalid CommandBlock data!"); // CraftBukkit |
1451 1448 | } finally { |
1452 1449 | packetdataserializer.release(); |
1453 1450 | } |
1454 - | |
1451 + | |
1455 1452 | } |
1456 1453 | } catch (Exception exception4) { |
1457 1454 | PlayerConnection.c.error("Couldn\'t set beacon", exception4); |
1458 1455 | + this.disconnect("Invalid beacon data!"); // CraftBukkit |
1459 1456 | } |
1460 1457 | } |
1461 1458 | } else if ("MC|ItemName".equals(packetplayincustompayload.a()) && this.player.activeContainer instanceof ContainerAnvil) { |
1462 - | |
1459 + | |
1463 1460 | containeranvil.a(""); |
1464 1461 | } |
1465 1462 | } |
1466 1463 | + // CraftBukkit start |
1467 1464 | + else if (packetplayincustompayload.a().equals("REGISTER")) { |
1468 1465 | + String channels = packetplayincustompayload.b().toString(com.google.common.base.Charsets.UTF_8); |
1469 1466 | + for (String channel : channels.split("\0")) { |
1470 1467 | + getPlayer().addChannel(channel); |
1471 1468 | + } |
1472 1469 | + } else if (packetplayincustompayload.a().equals("UNREGISTER")) { |