Commits

Thinkofname authored ba325926d5c
Revert: Don't try and disconnect twice
No tags

nms-patches/PlayerConnection.patch

Modified
1 ---- /home/matt/mc-dev-private//net/minecraft/server/PlayerConnection.java 2015-04-15 17:35:03.688828804 +0100
2 -+++ src/main/java/net/minecraft/server/PlayerConnection.java 2015-04-15 17:35:03.692828804 +0100
1 +--- /home/matt/mc-dev-private//net/minecraft/server/PlayerConnection.java 2015-04-17 11:54:58.464656095 +0100
2 ++++ src/main/java/net/minecraft/server/PlayerConnection.java 2015-04-17 11:54:58.468656095 +0100
3 3 @@ -17,6 +17,48 @@
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 -@@ -77,19 +152,31 @@
119 +@@ -77,19 +152,37 @@
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);
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 150 - public void run() {
151 151 - PlayerConnection.this.networkManager.l();
152 -- }
152 ++ // CraftBukkit - Don't wait
153 ++ this.minecraftServer.postToMainThread(new Runnable() {
154 ++ public void run() {
155 ++ PlayerConnection.this.networkManager.l();
156 + }
153 157 - }));
158 ++ });
154 159 }
155 160
156 161 public void a(PacketPlayInSteerVehicle packetplayinsteervehicle) {
157 -@@ -99,6 +186,17 @@
162 +@@ -99,6 +192,17 @@
158 163
159 164 public void a(PacketPlayInFlying packetplayinflying) {
160 165 PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.u());
161 166 + // CraftBukkit start - Check for NaN
162 167 + if (!NumberConversions.isFinite(packetplayinflying.x)
163 168 + || !NumberConversions.isFinite(packetplayinflying.y)
164 169 + || !NumberConversions.isFinite(packetplayinflying.z)
165 170 + || !NumberConversions.isFinite(packetplayinflying.yaw)
166 171 + || !NumberConversions.isFinite(packetplayinflying.pitch)) {
167 172 + c.warn(player.getName() + " was caught trying to crash the server with an invalid position.");
168 173 + getPlayer().kickPlayer("Nope!");
169 174 + return;
170 175 + }
171 176 + // CraftBukkit end
172 177 WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
173 178
174 179 this.h = true;
175 -@@ -117,8 +215,66 @@
180 +@@ -117,8 +221,66 @@
176 181 this.checkMovement = true;
177 182 }
178 183 }
179 184 + // CraftBukkit start - fire PlayerMoveEvent
180 185 + Player player = this.getPlayer();
181 186 + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
182 187 + Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
183 188 +
184 189 + // If the packet contains movement information then we update the To location with the correct XYZ.
185 190 + if (packetplayinflying.hasPos && !(packetplayinflying.hasPos && packetplayinflying.y == -999.0D)) {
233 238 + return;
234 239 + }
235 240 + }
236 241 + }
237 242 +
238 243 + if (this.checkMovement && !this.player.dead) {
239 244 + // CraftBukkit end
240 245 this.f = this.e;
241 246 double d7;
242 247 double d8;
243 -@@ -146,6 +302,7 @@
248 +@@ -146,6 +308,7 @@
244 249
245 250 this.minecraftServer.getPlayerList().d(this.player);
246 251 if (this.player.vehicle != null) {
247 252 + this.player.vehicle.ai = true; // CraftBukkit - moved from below
248 253 if (d3 > 4.0D) {
249 254 Entity entity = this.player.vehicle;
250 255
251 -@@ -153,7 +310,7 @@
256 +@@ -153,7 +316,7 @@
252 257 this.a(this.player.locX, this.player.locY, this.player.locZ, this.player.yaw, this.player.pitch);
253 258 }
254 259
255 260 - this.player.vehicle.ai = true;
256 261 + // this.player.vehicle.ai = true; // CraftBukkit - moved up
257 262 }
258 263
259 264 if (this.checkMovement) {
260 -@@ -212,12 +369,14 @@
265 +@@ -212,12 +375,14 @@
261 266 double d11 = d7 - this.player.locX;
262 267 double d12 = d8 - this.player.locY;
263 268 double d13 = d9 - this.player.locZ;
264 269 - double d14 = Math.min(Math.abs(d11), Math.abs(this.player.motX));
265 270 - double d15 = Math.min(Math.abs(d12), Math.abs(this.player.motY));
266 271 - double d16 = Math.min(Math.abs(d13), Math.abs(this.player.motZ));
267 272 + // CraftBukkit start - min to max
268 273 + double d14 = Math.max(Math.abs(d11), Math.abs(this.player.motX));
269 274 + double d15 = Math.max(Math.abs(d12), Math.abs(this.player.motY));
270 275 + double d16 = Math.max(Math.abs(d13), Math.abs(this.player.motZ));
271 276 + // CraftBukkit end
272 277 double d17 = d14 * d14 + d15 * d15 + d16 * d16;
273 278
274 279 - if (d17 > 100.0D && (!this.minecraftServer.S() || !this.minecraftServer.R().equals(this.player.getName()))) {
275 280 + 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
276 281 PlayerConnection.c.warn(this.player.getName() + " moved too quickly! " + d11 + "," + d12 + "," + d13 + " (" + d14 + ", " + d15 + ", " + d16 + ")");
277 282 this.a(this.o, this.p, this.q, this.player.yaw, this.player.pitch);
278 283 return;
279 -@@ -286,10 +445,53 @@
284 +@@ -286,10 +451,53 @@
280 285 }
281 286
282 287 public void a(double d0, double d1, double d2, float f, float f1) {
283 288 - this.a(d0, d1, d2, f, f1, Collections.emptySet());
284 289 + this.a(d0, d1, d2, f, f1, Collections.<PacketPlayOutPosition.EnumPlayerTeleportFlags>emptySet()); // CraftBukkit fix decompile errors
285 290 }
286 291
287 292 public void a(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set) {
288 293 + // CraftBukkit start - Delegate to teleport(Location)
289 294 + Player player = this.getPlayer();
324 329 + this.lastPosX = d0;
325 330 + this.lastPosY = d1;
326 331 + this.lastPosZ = d2;
327 332 + this.lastYaw = f;
328 333 + this.lastPitch = f1;
329 334 + this.justTeleported = true;
330 335 + // CraftBukkit end
331 336 this.checkMovement = false;
332 337 this.o = d0;
333 338 this.p = d1;
334 -@@ -323,32 +525,49 @@
339 +@@ -323,32 +531,49 @@
335 340
336 341 public void a(PacketPlayInBlockDig packetplayinblockdig) {
337 342 PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.u());
338 343 + if (this.player.dead) return; // CraftBukkit
339 344 WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
340 345 BlockPosition blockposition = packetplayinblockdig.a();
341 346
342 347 this.player.z();
343 348 + // CraftBukkit start
344 349 switch (PlayerConnection.SyntheticClass_1.a[packetplayinblockdig.c().ordinal()]) {
380 385
381 386 - case 4:
382 387 - case 5:
383 388 - case 6:
384 389 + case 4: // START_DESTROY_BLOCK
385 390 + case 5: // ABORT_DESTROY_BLOCK
386 391 + case 6: // STOP_DESTROY_BLOCK
387 392 double d0 = this.player.locX - ((double) blockposition.getX() + 0.5D);
388 393 double d1 = this.player.locY - ((double) blockposition.getY() + 0.5D) + 1.5D;
389 394 double d2 = this.player.locZ - ((double) blockposition.getZ() + 0.5D);
390 -@@ -363,7 +582,15 @@
395 +@@ -363,7 +588,15 @@
391 396 if (!this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) {
392 397 this.player.playerInteractManager.a(blockposition, packetplayinblockdig.b());
393 398 } else {
394 399 + // CraftBukkit start - fire PlayerInteractEvent
395 400 + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, packetplayinblockdig.b(), this.player.inventory.getItemInHand());
396 401 this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition));
397 402 + // Update any tile entity data for this block
398 403 + TileEntity tileentity = worldserver.getTileEntity(blockposition);
399 404 + if (tileentity != null) {
400 405 + this.player.playerConnection.sendPacket(tileentity.getUpdatePacket());
401 406 + }
402 407 + // CraftBukkit end
403 408 }
404 409 } else {
405 410 if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) {
406 -@@ -383,11 +610,22 @@
411 +@@ -383,11 +616,22 @@
407 412 default:
408 413 throw new IllegalArgumentException("Invalid player action");
409 414 }
410 415 + // CraftBukkit end
411 416 }
412 417
413 418 public void a(PacketPlayInBlockPlace packetplayinblockplace) {
414 419 PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.u());
415 420 WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
416 421 +
419 424 +
420 425 + // CraftBukkit - if rightclick decremented the item, always send the update packet. */
421 426 + // this is not here for CraftBukkit's own functionality; rather it is to fix
422 427 + // a notch bug where the item doesn't update correctly.
423 428 + boolean always = false;
424 429 + // CraftBukkit end
425 430 +
426 431 ItemStack itemstack = this.player.inventory.getItemInHand();
427 432 boolean flag = false;
428 433 BlockPosition blockposition = packetplayinblockplace.a();
429 -@@ -399,7 +637,50 @@
434 +@@ -399,7 +643,50 @@
430 435 return;
431 436 }
432 437
433 438 - this.player.playerInteractManager.useItem(this.player, worldserver, itemstack);
434 439 + // CraftBukkit start
435 440 + int itemstackAmount = itemstack.count;
436 441 +
437 442 + // Raytrace to look for 'rogue armswings'
438 443 + float f1 = this.player.pitch;
439 444 + float f2 = this.player.yaw;
471 476 + }
472 477 +
473 478 + // CraftBukkit - notch decrements the counter by 1 in the above method with food,
474 479 + // snowballs and so forth, but he does it in a place that doesn't cause the
475 480 + // inventory update packet to get sent
476 481 + always = (itemstack.count != itemstackAmount) || itemstack.getItem() == Item.getItemOf(Blocks.WATERLILY);
477 482 + // CraftBukkit end
478 483 } else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight() - 1 && (enumdirection == EnumDirection.UP || blockposition.getY() >= this.minecraftServer.getMaxBuildHeight())) {
479 484 ChatMessage chatmessage = new ChatMessage("build.tooHigh", new Object[] { Integer.valueOf(this.minecraftServer.getMaxBuildHeight())});
480 485
481 -@@ -407,8 +688,19 @@
486 +@@ -407,8 +694,19 @@
482 487 this.player.playerConnection.sendPacket(new PacketPlayOutChat(chatmessage));
483 488 flag = true;
484 489 } else {
485 490 + // CraftBukkit start - Check if we can actually do something over this large a distance
486 491 + Location eyeLoc = this.getPlayer().getEyeLocation();
487 492 + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ());
488 493 + if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) {
489 494 + return;
490 495 + }
491 496 +
492 497 + if (!worldserver.getWorldBorder().a(blockposition)) {
493 498 + return;
494 499 + }
495 500 +
496 501 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)) {
497 502 - this.player.playerInteractManager.interact(this.player, worldserver, itemstack, blockposition, enumdirection, packetplayinblockplace.d(), packetplayinblockplace.e(), packetplayinblockplace.f());
498 503 + always = !this.player.playerInteractManager.interact(this.player, worldserver, itemstack, blockposition, enumdirection, packetplayinblockplace.d(), packetplayinblockplace.e(), packetplayinblockplace.f());
499 504 }
500 505
501 506 flag = true;
502 -@@ -432,7 +724,8 @@
507 +@@ -432,7 +730,8 @@
503 508
504 509 this.player.activeContainer.b();
505 510 this.player.g = false;
506 511 - if (!ItemStack.matches(this.player.inventory.getItemInHand(), packetplayinblockplace.getItemStack())) {
507 512 + // 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
508 513 + if (!ItemStack.matches(this.player.inventory.getItemInHand(), packetplayinblockplace.getItemStack()) || always) {
509 514 this.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, slot.rawSlotIndex, this.player.inventory.getItemInHand()));
510 515 }
511 516 }
512 -@@ -446,8 +739,8 @@
517 +@@ -446,8 +745,8 @@
513 518 WorldServer[] aworldserver = this.minecraftServer.worldServer;
514 519 int i = aworldserver.length;
515 520
516 521 - for (int j = 0; j < i; ++j) {
517 522 - WorldServer worldserver = aworldserver[j];
518 523 + // CraftBukkit - use the worlds array list
519 524 + for (WorldServer worldserver : minecraftServer.worlds) {
520 525
521 526 if (worldserver != null) {
522 527 entity = packetplayinspectate.a(worldserver);
523 -@@ -460,6 +753,8 @@
528 +@@ -460,6 +759,8 @@
524 529 if (entity != null) {
525 530 this.player.e((Entity) this.player);
526 531 this.player.mount((Entity) null);
527 532 +
528 533 + /* CraftBukkit start - replace with bukkit handling for multi-world
529 534 if (entity.world != this.player.world) {
530 535 WorldServer worldserver1 = this.player.u();
531 536 WorldServer worldserver2 = (WorldServer) entity.world;
532 -@@ -484,6 +779,9 @@
537 +@@ -484,6 +785,9 @@
533 538 } else {
534 539 this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ);
535 540 }
536 541 + */
537 542 + this.player.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE);
538 543 + // CraftBukkit end
539 544 }
540 545 }
541 546
542 -@@ -492,14 +790,29 @@
547 +@@ -492,14 +796,29 @@
543 548 public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) {}
544 549
545 550 public void a(IChatBaseComponent ichatbasecomponent) {
546 551 - PlayerConnection.c.info(this.player.getName() + " lost connection: " + ichatbasecomponent);
547 552 + // CraftBukkit start - Rarely it would send a disconnect line twice
548 553 + if (this.processedDisconnect) {
549 554 + return;
550 555 + } else {
551 556 + this.processedDisconnect = true;
552 557 + }
564 569 this.player.q();
565 570 - this.minecraftServer.getPlayerList().disconnect(this.player);
566 571 + String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player);
567 572 + if ((quitMessage != null) && (quitMessage.length() > 0)) {
568 573 + this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage));
569 574 + }
570 575 + // CraftBukkit end
571 576 if (this.minecraftServer.S() && this.player.getName().equals(this.minecraftServer.R())) {
572 577 PlayerConnection.c.info("Stopping singleplayer server as player logged out");
573 578 this.minecraftServer.safeShutdown();
574 -@@ -521,6 +834,15 @@
579 +@@ -521,6 +840,15 @@
575 580 }
576 581 }
577 582
578 583 + // CraftBukkit start
579 584 + if (packet == null) {
580 585 + return;
581 586 + } else if (packet instanceof PacketPlayOutSpawnPosition) {
582 587 + PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet;
583 588 + this.player.compassTarget = new Location(this.getPlayer().getWorld(), packet6.position.getX(), packet6.position.getY(), packet6.position.getZ());
584 589 + }
585 590 + // CraftBukkit end
586 591 +
587 592 try {
588 593 this.networkManager.handle(packet);
589 594 } catch (Throwable throwable) {
590 -@@ -541,18 +863,34 @@
595 +@@ -541,18 +869,34 @@
591 596 }
592 597
593 598 public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) {
594 599 + // CraftBukkit start
595 600 + if (this.player.dead) return;
596 601 PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.u());
597 602 if (packetplayinhelditemslot.a() >= 0 && packetplayinhelditemslot.a() < PlayerInventory.getHotbarSize()) {
598 603 + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.a());
599 604 + this.server.getPluginManager().callEvent(event);
600 605 + if (event.isCancelled()) {
617 622 + // CraftBukkit start - async chat
618 623 + boolean isSync = packetplayinchat.a().startsWith("/");
619 624 + if (packetplayinchat.a().startsWith("/")) {
620 625 + PlayerConnectionUtils.ensureMainThread(packetplayinchat, this, this.player.u());
621 626 + }
622 627 + // CraftBukkit end
623 628 + if (this.player.dead || this.player.getChatFlags() == EntityHuman.EnumChatVisibility.HIDDEN) { // CraftBukkit - dead men tell no tales
624 629 ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]);
625 630
626 631 chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
627 -@@ -565,39 +903,249 @@
632 +@@ -565,39 +909,249 @@
628 633
629 634 for (int i = 0; i < s.length(); ++i) {
630 635 if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) {
631 636 - this.disconnect("Illegal characters in chat");
632 637 + // CraftBukkit start - threadsafety
633 638 + if (!isSync) {
634 639 + Waitable waitable = new Waitable() {
635 640 + @Override
636 641 + protected Object evaluate() {
637 642 + PlayerConnection.this.disconnect("Illegal characters in chat");
875 880 +
876 881 + if (e2.isCancelled()) {
877 882 + return;
878 883 + }
879 884 + break;
880 885 + }
881 886 + // CraftBukkit end
882 887 this.player.z();
883 888 switch (PlayerConnection.SyntheticClass_1.b[packetplayinentityaction.b().ordinal()]) {
884 889 case 1:
885 -@@ -618,7 +1166,7 @@
890 +@@ -618,7 +1172,7 @@
886 891
887 892 case 5:
888 893 this.player.a(false, true, true);
889 894 - this.checkMovement = false;
890 895 + // this.checkMovement = false; // CraftBukkit - this is handled in teleport
891 896 break;
892 897
893 898 case 6:
894 -@@ -640,6 +1188,7 @@
899 +@@ -640,6 +1194,7 @@
895 900 }
896 901
897 902 public void a(PacketPlayInUseEntity packetplayinuseentity) {
898 903 + if (this.player.dead) return; // CraftBukkit
899 904 PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.u());
900 905 WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
901 906 Entity entity = packetplayinuseentity.a((World) worldserver);
902 -@@ -654,18 +1203,67 @@
907 +@@ -654,18 +1209,67 @@
903 908 }
904 909
905 910 if (this.player.h(entity) < d0) {
906 911 + ItemStack itemInHand = this.player.inventory.getItemInHand(); // CraftBukkit
907 912 +
908 913 + if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT
909 914 + || packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) {
910 915 + // CraftBukkit start
911 916 + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient;
912 917 + Item origItem = this.player.inventory.getItemInHand() == null ? null : this.player.inventory.getItemInHand().getItem();
961 966 this.player.attack(entity);
962 967 +
963 968 + // CraftBukkit start
964 969 + if (itemInHand != null && itemInHand.count <= -1) {
965 970 + this.player.updateInventory(this.player.activeContainer);
966 971 + }
967 972 + // CraftBukkit end
968 973 }
969 974 }
970 975 }
971 -@@ -680,7 +1278,8 @@
976 +@@ -680,7 +1284,8 @@
972 977 switch (PlayerConnection.SyntheticClass_1.c[packetplayinclientcommand_enumclientcommand.ordinal()]) {
973 978 case 1:
974 979 if (this.player.viewingCredits) {
975 980 - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true);
976 981 + // this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true);
977 982 + this.minecraftServer.getPlayerList().changeDimension(this.player, 0, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management
978 983 } else if (this.player.u().getWorldData().isHardcore()) {
979 984 if (this.minecraftServer.S() && this.player.getName().equals(this.minecraftServer.R())) {
980 985 this.player.playerConnection.disconnect("You have died. Game over, man, it\'s game over!");
981 -@@ -711,15 +1310,21 @@
986 +@@ -711,15 +1316,21 @@
982 987 }
983 988
984 989 public void a(PacketPlayInCloseWindow packetplayinclosewindow) {
985 990 + if (this.player.dead) return; // CraftBukkit
986 991 PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.u());
987 992 +
988 993 + CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit
989 994 +
990 995 this.player.p();
991 996 }
994 999 + if (this.player.dead) return; // CraftBukkit
995 1000 PlayerConnectionUtils.ensureMainThread(packetplayinwindowclick, this, this.player.u());
996 1001 this.player.z();
997 1002 if (this.player.activeContainer.windowId == packetplayinwindowclick.a() && this.player.activeContainer.c(this.player)) {
998 1003 - if (this.player.v()) {
999 1004 + boolean cancelled = this.player.v(); // CraftBukkit - see below if
1000 1005 + if (false) { // CraftBukkit this.player.v()) {
1001 1006 ArrayList arraylist = Lists.newArrayList();
1002 1007
1003 1008 for (int i = 0; i < this.player.activeContainer.c.size(); ++i) {
1004 -@@ -728,7 +1333,270 @@
1009 +@@ -728,7 +1339,270 @@
1005 1010
1006 1011 this.player.a(this.player.activeContainer, (List) arraylist);
1007 1012 } else {
1008 1013 - ItemStack itemstack = this.player.activeContainer.clickItem(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player);
1009 1014 + // ItemStack itemstack = this.player.activeContainer.clickItem(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player);
1010 1015 + // CraftBukkit start - Call InventoryClickEvent
1011 1016 + if (packetplayinwindowclick.b() < -1 && packetplayinwindowclick.b() != -999) {
1012 1017 + return;
1013 1018 + }
1014 1019 +
1266 1271 + if (event instanceof CraftItemEvent) {
1267 1272 + // Need to update the inventory on crafting to
1268 1273 + // correctly support custom recipes
1269 1274 + player.updateInventory(player.activeContainer);
1270 1275 + }
1271 1276 + }
1272 1277 + // CraftBukkit end
1273 1278
1274 1279 if (ItemStack.matches(packetplayinwindowclick.e(), itemstack)) {
1275 1280 this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), true));
1276 -@@ -789,8 +1657,48 @@
1281 +@@ -789,8 +1663,48 @@
1277 1282 }
1278 1283
1279 1284 boolean flag1 = packetplayinsetcreativeslot.a() >= 1 && packetplayinsetcreativeslot.a() < 36 + PlayerInventory.getHotbarSize();
1280 1285 - boolean flag2 = itemstack == null || itemstack.getItem() != null;
1281 1286 + // CraftBukkit - Add invalidItems check
1282 1287 + boolean flag2 = itemstack == null || itemstack.getItem() != null && !invalidItems.contains(Item.getId(itemstack.getItem()));
1283 1288 boolean flag3 = itemstack == null || itemstack.getData() >= 0 && itemstack.count <= 64 && itemstack.count > 0;
1284 1289 + // CraftBukkit start - Call click event
1285 1290 + if (flag || (flag1 && !ItemStack.matches(this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem(), packetplayinsetcreativeslot.getItemStack()))) { // Insist on valid slot
1286 1291 +
1316 1321 + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.defaultContainer.windowId, packetplayinsetcreativeslot.a(), this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem()));
1317 1322 + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, null));
1318 1323 + }
1319 1324 + return;
1320 1325 + }
1321 1326 + }
1322 1327 + // CraftBukkit end
1323 1328
1324 1329 if (flag1 && flag2 && flag3) {
1325 1330 if (itemstack == null) {
1326 -@@ -813,6 +1721,7 @@
1331 +@@ -813,6 +1727,7 @@
1327 1332 }
1328 1333
1329 1334 public void a(PacketPlayInTransaction packetplayintransaction) {
1330 1335 + if (this.player.dead) return; // CraftBukkit
1331 1336 PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.u());
1332 1337 Short oshort = (Short) this.n.get(this.player.activeContainer.windowId);
1333 1338
1334 -@@ -823,6 +1732,7 @@
1339 +@@ -823,6 +1738,7 @@
1335 1340 }
1336 1341
1337 1342 public void a(PacketPlayInUpdateSign packetplayinupdatesign) {
1338 1343 + if (this.player.dead) return; // CraftBukkit
1339 1344 PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.u());
1340 1345 this.player.z();
1341 1346 WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
1342 -@@ -839,14 +1749,30 @@
1347 +@@ -839,14 +1755,30 @@
1343 1348
1344 1349 if (!tileentitysign.b() || tileentitysign.c() != this.player) {
1345 1350 this.minecraftServer.warning("Player " + this.player.getName() + " just tried to change non-editable sign");
1346 1351 + this.sendPacket(new PacketPlayOutUpdateSign(tileentity.world, packetplayinupdatesign.a(), tileentitysign.lines)); // CraftBukkit
1347 1352 return;
1348 1353 }
1349 1354
1350 1355 IChatBaseComponent[] aichatbasecomponent = packetplayinupdatesign.b();
1351 1356
1352 1357 + // CraftBukkit start
1364 1369 +
1365 1370 + if (!event.isCancelled()) {
1366 1371 + System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4);
1367 1372 + tileentitysign.isEditable = false;
1368 1373 }
1369 1374 + // System.arraycopy(packetplayinupdatesign.b(), 0, tileentitysign.lines, 0, 4);
1370 1375 + // CraftBukkit end
1371 1376
1372 1377 tileentitysign.update();
1373 1378 worldserver.notify(blockposition);
1374 -@@ -869,11 +1795,27 @@
1379 +@@ -869,11 +1801,27 @@
1375 1380
1376 1381 public void a(PacketPlayInAbilities packetplayinabilities) {
1377 1382 PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.u());
1378 1383 - this.player.abilities.isFlying = packetplayinabilities.isFlying() && this.player.abilities.canFly;
1379 1384 + // CraftBukkit start
1380 1385 + if (this.player.abilities.canFly && this.player.abilities.isFlying != packetplayinabilities.isFlying()) {
1381 1386 + PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.server.getPlayer(this.player), packetplayinabilities.isFlying());
1382 1387 + this.server.getPluginManager().callEvent(event);
1383 1388 + if (!event.isCancelled()) {
1384 1389 + this.player.abilities.isFlying = packetplayinabilities.isFlying(); // Actually set the player's flying status
1393 1398 PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.u());
1394 1399 + // CraftBukkit start
1395 1400 + if (chatSpamField.addAndGet(this, 10) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) {
1396 1401 + this.disconnect("disconnect.spam");
1397 1402 + return;
1398 1403 + }
1399 1404 + // CraftBukkit end
1400 1405 ArrayList arraylist = Lists.newArrayList();
1401 1406 Iterator iterator = this.minecraftServer.tabCompleteCommand(this.player, packetplayintabcomplete.a(), packetplayintabcomplete.b()).iterator();
1402 1407
1403 -@@ -913,13 +1855,16 @@
1408 +@@ -913,13 +1861,16 @@
1404 1409 itemstack1 = this.player.inventory.getItemInHand();
1405 1410 if (itemstack1 != null) {
1406 1411 if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack.getItem() == itemstack1.getItem()) {
1407 1412 + itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit
1408 1413 itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8));
1409 1414 + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit
1410 1415 }
1411 1416
1412 1417 return;
1413 1418 }
1414 1419 } catch (Exception exception) {
1415 1420 PlayerConnection.c.error("Couldn\'t handle book info", exception);
1416 1421 + this.disconnect("Invalid book data!"); // CraftBukkit
1417 1422 return;
1418 1423 } finally {
1419 1424 packetdataserializer.release();
1420 -@@ -942,16 +1887,21 @@
1425 +@@ -942,16 +1893,21 @@
1421 1426 itemstack1 = this.player.inventory.getItemInHand();
1422 1427 if (itemstack1 != null) {
1423 1428 if (itemstack.getItem() == Items.WRITTEN_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) {
1424 1429 + // CraftBukkit start
1425 1430 + itemstack1 = new ItemStack(Items.WRITTEN_BOOK);
1426 1431 itemstack1.a("author", (NBTBase) (new NBTTagString(this.player.getName())));
1427 1432 itemstack1.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title"))));
1428 1433 itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8));
1429 1434 itemstack1.setItem(Items.WRITTEN_BOOK);
1430 1435 + CraftEventFactory.handleEditBookEvent(player, itemstack1);
1431 1436 + // CraftBukkit end
1432 1437 }
1433 1438
1434 1439 return;
1435 1440 }
1436 1441 } catch (Exception exception1) {
1437 1442 PlayerConnection.c.error("Couldn\'t sign book", exception1);
1438 1443 + this.disconnect("Invalid book data!"); // CraftBukkit
1439 1444 return;
1440 1445 } finally {
1441 1446 packetdataserializer.release();
1442 -@@ -968,11 +1918,12 @@
1447 +@@ -968,11 +1924,12 @@
1443 1448 }
1444 1449 } catch (Exception exception2) {
1445 1450 PlayerConnection.c.error("Couldn\'t select trade", exception2);
1446 1451 + this.disconnect("Invalid trade data!"); // CraftBukkit
1447 1452 }
1448 1453 } else if ("MC|AdvCdm".equals(packetplayincustompayload.a())) {
1449 1454 if (!this.minecraftServer.getEnableCommandBlock()) {
1450 1455 this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0]));
1451 1456 - } else if (this.player.a(2, "") && this.player.abilities.canInstantlyBuild) {
1452 1457 + } else if (this.player.getBukkitEntity().isOp() && this.player.abilities.canInstantlyBuild) { // CraftBukkit - Change to Bukkit OP versus Vanilla OP
1453 1458 packetdataserializer = packetplayincustompayload.b();
1454 1459
1455 1460 try {
1456 -@@ -1008,6 +1959,7 @@
1461 +@@ -1008,6 +1965,7 @@
1457 1462 }
1458 1463 } catch (Exception exception3) {
1459 1464 PlayerConnection.c.error("Couldn\'t set command block", exception3);
1460 1465 + this.disconnect("Invalid CommandBlock data!"); // CraftBukkit
1461 1466 } finally {
1462 1467 packetdataserializer.release();
1463 1468 }
1464 -@@ -1033,6 +1985,7 @@
1469 +@@ -1033,6 +1991,7 @@
1465 1470 }
1466 1471 } catch (Exception exception4) {
1467 1472 PlayerConnection.c.error("Couldn\'t set beacon", exception4);
1468 1473 + this.disconnect("Invalid beacon data!"); // CraftBukkit
1469 1474 }
1470 1475 }
1471 1476 } else if ("MC|ItemName".equals(packetplayincustompayload.a()) && this.player.activeContainer instanceof ContainerAnvil) {
1472 -@@ -1048,7 +2001,28 @@
1477 +@@ -1048,7 +2007,28 @@
1473 1478 containeranvil.a("");
1474 1479 }
1475 1480 }
1476 1481 + // CraftBukkit start
1477 1482 + else if (packetplayincustompayload.a().equals("REGISTER")) {
1478 1483 + String channels = packetplayincustompayload.b().toString(com.google.common.base.Charsets.UTF_8);
1479 1484 + for (String channel : channels.split("\0")) {
1480 1485 + getPlayer().addChannel(channel);
1481 1486 + }
1482 1487 + } else if (packetplayincustompayload.a().equals("UNREGISTER")) {

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

Add shortcut