Commits

Christopher Bohn authored and md_5 committed eb7a2dcc515
#1003: Fix cancellation of TradeSelectEvent
No tags

nms-patches/net/minecraft/server/network/PlayerConnection.patch

Modified
337 337
338 338 if (stringreader.canRead() && stringreader.peek() == '/') {
339 339 @@ -483,6 +696,7 @@
340 340 ParseResults<CommandListenerWrapper> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
341 341
342 342 this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
343 343 + if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
344 344 this.connection.send(new PacketPlayOutTabComplete(packetplayintabcomplete.getId(), suggestions));
345 345 });
346 346 }
347 -@@ -715,6 +929,7 @@
347 +@@ -715,6 +929,13 @@
348 348
349 349 if (container instanceof ContainerMerchant) {
350 350 ContainerMerchant containermerchant = (ContainerMerchant) container;
351 -+ CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); // CraftBukkit
351 ++ // CraftBukkit start
352 ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant);
353 ++ if (tradeSelectEvent.isCancelled()) {
354 ++ this.player.getBukkitEntity().updateInventory();
355 ++ return;
356 ++ }
357 ++ // CraftBukkit end
352 358
353 359 containermerchant.setSelectionHint(i);
354 360 containermerchant.tryMoveItems(i);
355 -@@ -724,6 +939,13 @@
361 +@@ -724,6 +945,13 @@
356 362
357 363 @Override
358 364 public void handleEditBook(PacketPlayInBEdit packetplayinbedit) {
359 365 + // CraftBukkit start
360 366 + if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
361 367 + this.disconnect("Book edited too quickly!");
362 368 + return;
363 369 + }
364 370 + this.lastBookTick = MinecraftServer.currentTick;
365 371 + // CraftBukkit end
366 372 int i = packetplayinbedit.getSlot();
367 373
368 374 if (PlayerInventory.isHotbarSlot(i) || i == 40) {
369 -@@ -732,7 +954,7 @@
375 +@@ -732,7 +960,7 @@
370 376
371 377 Objects.requireNonNull(list);
372 378 optional.ifPresent(list::add);
373 379 - Stream stream = packetplayinbedit.getPages().stream().limit(100L);
374 380 + Stream<String> stream = packetplayinbedit.getPages().stream().limit(100L); // CraftBukkit - decompile error
375 381
376 382 Objects.requireNonNull(list);
377 383 stream.forEach(list::add);
378 -@@ -748,7 +970,7 @@
384 +@@ -748,7 +976,7 @@
379 385 ItemStack itemstack = this.player.getInventory().getItem(i);
380 386
381 387 if (itemstack.is(Items.WRITABLE_BOOK)) {
382 388 - this.updateBookPages(list, UnaryOperator.identity(), itemstack);
383 389 + this.updateBookPages(list, UnaryOperator.identity(), itemstack.copy(), i, itemstack); // CraftBukkit
384 390 }
385 391 }
386 392
387 -@@ -773,16 +995,16 @@
393 +@@ -773,16 +1001,16 @@
388 394
389 395 this.updateBookPages(list, (s) -> {
390 396 return IChatBaseComponent.ChatSerializer.toJson(new ChatComponentText(s));
391 397 - }, itemstack1);
392 398 - this.player.getInventory().setItem(i, itemstack1);
393 399 + }, itemstack1, i, itemstack); // CraftBukkit
394 400 + this.player.getInventory().setItem(i, itemstack); // CraftBukkit - event factory updates the hand book
395 401 }
396 402 }
397 403
398 404 - private void updateBookPages(List<ITextFilter.a> list, UnaryOperator<String> unaryoperator, ItemStack itemstack) {
399 405 + private void updateBookPages(List<ITextFilter.a> list, UnaryOperator<String> unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit
400 406 NBTTagList nbttaglist = new NBTTagList();
401 407
402 408 if (this.player.isTextFilteringEnabled()) {
403 409 - Stream stream = list.stream().map((itextfilter_a) -> {
404 410 + Stream<NBTTagString> stream = list.stream().map((itextfilter_a) -> { // CraftBukkit - decompile error
405 411 return NBTTagString.valueOf((String) unaryoperator.apply(itextfilter_a.getFiltered()));
406 412 });
407 413
408 -@@ -810,6 +1032,7 @@
414 +@@ -810,6 +1038,7 @@
409 415 }
410 416
411 417 itemstack.addTagElement("pages", nbttaglist);
412 418 + CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit
413 419 }
414 420
415 421 @Override
416 -@@ -846,7 +1069,7 @@
422 +@@ -846,7 +1075,7 @@
417 423 } else {
418 424 WorldServer worldserver = this.player.getLevel();
419 425
420 426 - if (!this.player.wonGame) {
421 427 + if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit
422 428 if (this.tickCount == 0) {
423 429 this.resetPosition();
424 430 }
425 -@@ -856,7 +1079,7 @@
431 +@@ -856,7 +1085,7 @@
426 432 this.awaitingTeleportTime = this.tickCount;
427 433 this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
428 434 }
429 435 -
430 436 + this.allowedPlayerTicks = 20; // CraftBukkit
431 437 } else {
432 438 this.awaitingTeleportTime = this.tickCount;
433 439 double d0 = clampHorizontal(packetplayinflying.getX(this.player.getX()));
434 -@@ -868,7 +1091,15 @@
440 +@@ -868,7 +1097,15 @@
435 441 if (this.player.isPassenger()) {
436 442 this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1);
437 443 this.player.getLevel().getChunkSource().move(this.player);
438 444 + this.allowedPlayerTicks = 20; // CraftBukkit
439 445 } else {
440 446 + // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify
441 447 + double prevX = player.getX();
442 448 + double prevY = player.getY();
443 449 + double prevZ = player.getZ();
444 450 + float prevYaw = player.getYRot();
445 451 + float prevPitch = player.getXRot();
446 452 + // CraftBukkit end
447 453 double d3 = this.player.getX();
448 454 double d4 = this.player.getY();
449 455 double d5 = this.player.getZ();
450 -@@ -888,15 +1119,33 @@
456 +@@ -888,15 +1125,33 @@
451 457 ++this.receivedMovePacketCount;
452 458 int i = this.receivedMovePacketCount - this.knownMovePacketCount;
453 459
454 460 - if (i > 5) {
455 461 + // CraftBukkit start - handle custom speeds and skipped ticks
456 462 + this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
457 463 + this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1);
458 464 + this.lastTick = (int) (System.currentTimeMillis() / 50);
459 465 +
460 466 + if (i > Math.max(this.allowedPlayerTicks, 5)) {
476 482 +
477 483 if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) {
478 484 float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;
479 485
480 486 - if (d11 - d10 > (double) (f2 * (float) i) && !this.isSingleplayerOwner()) {
481 487 + if (d11 - d10 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
482 488 + // CraftBukkit end
483 489 PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d7, d8, d9);
484 490 this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
485 491 return;
486 -@@ -915,6 +1164,7 @@
492 +@@ -915,6 +1170,7 @@
487 493 }
488 494
489 495 this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9));
490 496 + this.player.onGround = packetplayinflying.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
491 497 double d12 = d8;
492 498
493 499 d7 = d0 - this.player.getX();
494 -@@ -936,7 +1186,71 @@
500 +@@ -936,7 +1192,71 @@
495 501 if (!this.player.noPhysics && !this.player.isSleeping() && (flag1 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) {
496 502 this.teleport(d3, d4, d5, f, f1);
497 503 } else {
498 504 - this.clientIsFloating = d12 >= -0.03125D && this.player.gameMode.getGameModeForPlayer() != EnumGamemode.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && this.noBlocksAround(this.player);
499 505 + // CraftBukkit start - fire PlayerMoveEvent
500 506 + // Rest to old location first
501 507 + this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch);
502 508 +
503 509 + Player player = this.getCraftPlayer();
504 510 + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
557 563 + }
558 564 + }
559 565 + this.player.absMoveTo(d0, d1, d2, f, f1); // Copied from above
560 566 +
561 567 + // MC-135989, SPIGOT-5564: isRiptiding
562 568 + this.clientIsFloating = d12 >= -0.03125D && this.player.gameMode.getGameModeForPlayer() != EnumGamemode.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && this.noBlocksAround(this.player) && !this.player.isAutoSpinAttack();
563 569 + // CraftBukkit end
564 570 this.player.getLevel().getChunkSource().move(this.player);
565 571 this.player.doCheckFallDamage(this.player.getY() - d6, packetplayinflying.isOnGround());
566 572 this.player.setOnGround(packetplayinflying.isOnGround());
567 -@@ -974,19 +1288,80 @@
573 +@@ -974,19 +1294,80 @@
568 574 return true;
569 575 }
570 576
571 577 + // CraftBukkit start - Delegate to teleport(Location)
572 578 public void dismount(double d0, double d1, double d2, float f, float f1) {
573 579 - this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), true);
574 580 + this.dismount(d0, d1, d2, f, f1, PlayerTeleportEvent.TeleportCause.UNKNOWN);
575 581 + }
576 582 +
577 583 + public void dismount(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) {
583 589 + this.teleport(d0, d1, d2, f, f1, PlayerTeleportEvent.TeleportCause.UNKNOWN);
584 590 + }
585 591 +
586 592 + public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) {
587 593 + this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), false, cause);
588 594 }
589 595
590 596 public void teleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set) {
591 597 - this.teleport(d0, d1, d2, f, f1, set, false);
592 598 + this.teleport(d0, d1, d2, f, f1, set, PlayerTeleportEvent.TeleportCause.UNKNOWN);
593 - }
594 -
595 -- public void teleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set, boolean flag) {
599 ++ }
600 ++
596 601 + public void teleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set, PlayerTeleportEvent.TeleportCause cause) {
597 602 + this.teleport(d0, d1, d2, f, f1, set, false, cause);
598 603 + }
599 604 +
600 605 + public boolean teleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set, boolean flag, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status
601 606 + Player player = this.getCraftPlayer();
602 607 + Location from = player.getLocation();
603 608 +
604 609 + double x = d0;
605 610 + double y = d1;
622 627 + to = event.isCancelled() ? event.getFrom() : event.getTo();
623 628 + d0 = to.getX();
624 629 + d1 = to.getY();
625 630 + d2 = to.getZ();
626 631 + f = to.getYaw();
627 632 + f1 = to.getPitch();
628 633 + }
629 634 +
630 635 + this.internalTeleport(d0, d1, d2, f, f1, set, flag);
631 636 + return event.isCancelled(); // CraftBukkit - Return event status
632 -+ }
633 -+
637 + }
638 +
639 +- public void teleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set, boolean flag) {
634 640 + public void teleport(Location dest) {
635 641 + internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.<PacketPlayOutPosition.EnumPlayerTeleportFlags>emptySet(), true);
636 642 + }
637 643 +
638 644 + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set, boolean flag) {
639 645 + // CraftBukkit start
640 646 + if (Float.isNaN(f)) {
641 647 + f = 0;
642 648 + }
643 649 + if (Float.isNaN(f1)) {
644 650 + f1 = 0;
645 651 + }
646 652 +
647 653 + this.justTeleported = true;
648 654 + // CraftBukkit end
649 655 double d3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X) ? this.player.getX() : 0.0D;
650 656 double d4 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y) ? this.player.getY() : 0.0D;
651 657 double d5 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Z) ? this.player.getZ() : 0.0D;
652 -@@ -998,6 +1373,14 @@
658 +@@ -998,6 +1379,14 @@
653 659 this.awaitingTeleport = 0;
654 660 }
655 661
656 662 + // CraftBukkit start - update last location
657 663 + this.lastPosX = this.awaitingPositionFromClient.x;
658 664 + this.lastPosY = this.awaitingPositionFromClient.y;
659 665 + this.lastPosZ = this.awaitingPositionFromClient.z;
660 666 + this.lastYaw = f;
661 667 + this.lastPitch = f1;
662 668 + // CraftBukkit end
663 669 +
664 670 this.awaitingTeleportTime = this.tickCount;
665 671 this.player.absMoveTo(d0, d1, d2, f, f1);
666 672 this.player.connection.send(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag));
667 -@@ -1006,6 +1389,7 @@
673 +@@ -1006,6 +1395,7 @@
668 674 @Override
669 675 public void handlePlayerAction(PacketPlayInBlockDig packetplayinblockdig) {
670 676 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockdig, this, this.player.getLevel());
671 677 + if (this.player.isImmobile()) return; // CraftBukkit
672 678 BlockPosition blockposition = packetplayinblockdig.getPos();
673 679
674 680 this.player.resetLastActionTime();
675 -@@ -1016,14 +1400,46 @@
681 +@@ -1016,14 +1406,46 @@
676 682 if (!this.player.isSpectator()) {
677 683 ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND);
678 684
679 685 - this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND));
680 686 - this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack);
681 687 + // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394)
682 688 + CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack);
683 689 + CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND));
684 690 + PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone());
685 691 + this.cserver.getPluginManager().callEvent(swapItemsEvent);
714 720 + if (this.dropCount >= 20) {
715 721 + LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!");
716 722 + this.disconnect("You dropped your items too quickly (Hacking?)");
717 723 + return;
718 724 + }
719 725 + }
720 726 + // CraftBukkit end
721 727 this.player.drop(false);
722 728 }
723 729
724 -@@ -1060,6 +1476,7 @@
730 +@@ -1060,6 +1482,7 @@
725 731 @Override
726 732 public void handleUseItemOn(PacketPlayInUseItem packetplayinuseitem) {
727 733 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseitem, this, this.player.getLevel());
728 734 + if (this.player.isImmobile()) return; // CraftBukkit
729 735 WorldServer worldserver = this.player.getLevel();
730 736 EnumHand enumhand = packetplayinuseitem.getHand();
731 737 ItemStack itemstack = this.player.getItemInHand(enumhand);
732 -@@ -1072,6 +1489,14 @@
738 +@@ -1072,6 +1495,14 @@
733 739
734 740 if (blockposition.getY() < i) {
735 741 if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) {
736 742 + // CraftBukkit start - Check if we can actually do something over this large a distance
737 743 + Location eyeLoc = this.getCraftPlayer().getEyeLocation();
738 744 + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ());
739 745 + if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) {
740 746 + return;
741 747 + }
742 748 + this.player.stopUsingItem(); // SPIGOT-4706
743 749 + // CraftBukkit end
744 750 EnumInteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);
745 751
746 752 if (enumdirection == EnumDirection.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) {
747 -@@ -1095,12 +1520,51 @@
753 +@@ -1095,12 +1526,51 @@
748 754 @Override
749 755 public void handleUseItem(PacketPlayInBlockPlace packetplayinblockplace) {
750 756 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockplace, this, this.player.getLevel());
751 757 + if (this.player.isImmobile()) return; // CraftBukkit
752 758 WorldServer worldserver = this.player.getLevel();
753 759 EnumHand enumhand = packetplayinblockplace.getHand();
754 760 ItemStack itemstack = this.player.getItemInHand(enumhand);
755 761
756 762 this.player.resetLastActionTime();
757 763 if (!itemstack.isEmpty()) {
789 795 + player.gameMode.firedInteract = false;
790 796 + }
791 797 +
792 798 + if (cancelled) {
793 799 + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524
794 800 + return;
795 801 + }
796 802 EnumInteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand);
797 803
798 804 if (enuminteractionresult.shouldSwing()) {
799 -@@ -1121,7 +1585,7 @@
805 +@@ -1121,7 +1591,7 @@
800 806 Entity entity = packetplayinspectate.getEntity(worldserver);
801 807
802 808 if (entity != null) {
803 809 - this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
804 810 + this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit
805 811 return;
806 812 }
807 813 }
808 -@@ -1136,6 +1600,7 @@
814 +@@ -1136,6 +1606,7 @@
809 815 PlayerConnection.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName());
810 816 this.disconnect(new ChatMessage("multiplayer.requiredTexturePrompt.disconnect"));
811 817 }
812 818 + this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.action.ordinal()])); // CraftBukkit
813 819
814 820 }
815 821
816 -@@ -1155,11 +1620,26 @@
822 +@@ -1155,11 +1626,26 @@
817 823
818 824 @Override
819 825 public void onDisconnect(IChatBaseComponent ichatbasecomponent) {
820 826 + // CraftBukkit start - Rarely it would send a disconnect line twice
821 827 + if (this.processedDisconnect) {
822 828 + return;
823 829 + } else {
824 830 + this.processedDisconnect = true;
825 831 + }
826 832 + // CraftBukkit end
834 840 this.player.disconnect();
835 841 - this.server.getPlayerList().remove(this.player);
836 842 + String quitMessage = this.server.getPlayerList().remove(this.player);
837 843 + if ((quitMessage != null) && (quitMessage.length() > 0)) {
838 844 + this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage));
839 845 + }
840 846 + // CraftBukkit end
841 847 this.player.getTextFilter().leave();
842 848 if (this.isSingleplayerOwner()) {
843 849 PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out");
844 -@@ -1174,6 +1654,15 @@
850 +@@ -1174,6 +1660,15 @@
845 851 }
846 852
847 853 public void send(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) {
848 854 + // CraftBukkit start
849 855 + if (packet == null) {
850 856 + return;
851 857 + } else if (packet instanceof PacketPlayOutSpawnPosition) {
852 858 + PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet;
853 859 + this.player.compassTarget = new Location(this.getCraftPlayer().getWorld(), packet6.pos.getX(), packet6.pos.getY(), packet6.pos.getZ());
854 860 + }
855 861 + // CraftBukkit end
856 862 +
857 863 try {
858 864 this.connection.send(packet, genericfuturelistener);
859 865 } catch (Throwable throwable) {
860 -@@ -1190,7 +1679,16 @@
866 +@@ -1190,7 +1685,16 @@
861 867 @Override
862 868 public void handleSetCarriedItem(PacketPlayInHeldItemSlot packetplayinhelditemslot) {
863 869 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinhelditemslot, this, this.player.getLevel());
864 870 + if (this.player.isImmobile()) return; // CraftBukkit
865 871 if (packetplayinhelditemslot.getSlot() >= 0 && packetplayinhelditemslot.getSlot() < PlayerInventory.getSelectionSize()) {
866 872 + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packetplayinhelditemslot.getSlot());
867 873 + this.cserver.getPluginManager().callEvent(event);
868 874 + if (event.isCancelled()) {
869 875 + this.send(new PacketPlayOutHeldItemSlot(this.player.getInventory().selected));
870 876 + this.player.resetLastActionTime();
871 877 + return;
872 878 + }
873 879 + // CraftBukkit end
874 880 if (this.player.getInventory().selected != packetplayinhelditemslot.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) {
875 881 this.player.stopUsingItem();
876 882 }
877 -@@ -1199,11 +1697,18 @@
883 +@@ -1199,11 +1703,18 @@
878 884 this.player.resetLastActionTime();
879 885 } else {
880 886 PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
881 887 + this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit
882 888 }
883 889 }
884 890
885 891 @Override
886 892 public void handleChat(PacketPlayInChat packetplayinchat) {
887 893 + // CraftBukkit start - async chat
888 894 + // SPIGOT-3638
889 895 + if (this.server.isStopped()) {
890 896 + return;
891 897 + }
892 898 + // CraftBukkit end
893 899 String s = StringUtils.normalizeSpace(packetplayinchat.getMessage());
894 900
895 901 for (int i = 0; i < s.length(); ++i) {
896 -@@ -1217,20 +1722,42 @@
902 +@@ -1217,20 +1728,42 @@
897 903 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinchat, this, this.player.getLevel());
898 904 this.handleChat(ITextFilter.a.passThrough(s));
899 905 } else {
900 906 - this.filterTextPacket(s, this::handleChat);
901 907 + this.handleChat(ITextFilter.a.passThrough(s)); // CraftBukkit - filter NYI
902 908 }
903 909
904 910 }
905 911
906 912 private void handleChat(ITextFilter.a itextfilter_a) {
933 939 + }
934 940 + });
935 941 + } else if (this.player.getChatVisibility() == EnumChatVisibility.SYSTEM) { // Re-add "Command Only" flag check
936 942 + this.send(new PacketPlayOutChat((new ChatMessage("chat.cannotSend")).withStyle(EnumChatFormat.RED), ChatMessageType.SYSTEM, SystemUtils.NIL_UUID));
937 943 + } else if (true) {
938 944 + this.chat(s, true);
939 945 + // CraftBukkit end - the below is for reference. :)
940 946 } else {
941 947 String s1 = itextfilter_a.getFiltered();
942 948 ChatMessage chatmessage = s1.isEmpty() ? null : new ChatMessage("chat.type.text", new Object[]{this.player.getDisplayName(), s1});
943 -@@ -1241,28 +1768,198 @@
949 +@@ -1241,28 +1774,198 @@
944 950 }, ChatMessageType.CHAT, this.player.getUUID());
945 951 }
946 952
947 953 - this.chatSpamTickCount += 20;
948 954 - if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
949 955 - this.disconnect(new ChatMessage("disconnect.spam"));
950 956 + // CraftBukkit start - replaced with thread safe throttle
951 957 + // this.chatSpamTickCount += 20;
952 958 + if (chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
953 959 + if (!isSync) {
1136 1142 +
1137 1143 + if (e2.isCancelled()) {
1138 1144 + return;
1139 1145 + }
1140 1146 + break;
1141 1147 + }
1142 1148 + // CraftBukkit end
1143 1149 this.player.resetLastActionTime();
1144 1150 IJumpable ijumpable;
1145 1151
1146 -@@ -1320,6 +2017,7 @@
1152 +@@ -1320,6 +2023,7 @@
1147 1153 @Override
1148 1154 public void handleInteract(PacketPlayInUseEntity packetplayinuseentity) {
1149 1155 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseentity, this, this.player.getLevel());
1150 1156 + if (this.player.isImmobile()) return; // CraftBukkit
1151 1157 WorldServer worldserver = this.player.getLevel();
1152 1158 final Entity entity = packetplayinuseentity.getTarget(worldserver);
1153 1159
1154 -@@ -1334,10 +2032,44 @@
1160 +@@ -1334,10 +2038,44 @@
1155 1161
1156 1162 if (this.player.distanceToSqr(entity) < 36.0D) {
1157 1163 packetplayinuseentity.dispatch(new PacketPlayInUseEntity.c() {
1158 1164 - private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a) {
1159 1165 + private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit
1160 1166 ItemStack itemstack = PlayerConnection.this.player.getItemInHand(enumhand).copy();
1161 1167 + // CraftBukkit start
1162 1168 + ItemStack itemInHand = PlayerConnection.this.player.getItemInHand(enumhand);
1163 1169 + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient;
1164 1170 + Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem();
1190 1196
1191 1197 + // CraftBukkit start
1192 1198 + if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) {
1193 1199 + player.containerMenu.sendAllDataToRemote();
1194 1200 + }
1195 1201 + // CraftBukkit end
1196 1202 +
1197 1203 if (enuminteractionresult.consumesAction()) {
1198 1204 CriterionTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(PlayerConnection.this.player, itemstack, entity);
1199 1205 if (enuminteractionresult.shouldSwing()) {
1200 -@@ -1349,20 +2081,27 @@
1206 +@@ -1349,20 +2087,27 @@
1201 1207
1202 1208 @Override
1203 1209 public void onInteraction(EnumHand enumhand) {
1204 1210 - this.performInteraction(enumhand, EntityHuman::interactOn);
1205 1211 + this.performInteraction(enumhand, EntityHuman::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (enumhand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND));
1206 1212 }
1207 1213
1208 1214 @Override
1209 1215 public void onInteraction(EnumHand enumhand, Vec3D vec3d) {
1210 1216 this.performInteraction(enumhand, (entityplayer, entity1, enumhand1) -> {
1221 1227 + ItemStack itemInHand = PlayerConnection.this.player.getMainHandItem();
1222 1228 PlayerConnection.this.player.attack(entity);
1223 1229 +
1224 1230 + if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) {
1225 1231 + player.containerMenu.sendAllDataToRemote();
1226 1232 + }
1227 1233 + // CraftBukkit end
1228 1234 } else {
1229 1235 PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked"));
1230 1236 PlayerConnection.LOGGER.warn("Player {} tried to attack an invalid entity", PlayerConnection.this.player.getName().getString());
1231 -@@ -1407,21 +2146,304 @@
1237 +@@ -1407,21 +2152,304 @@
1232 1238 @Override
1233 1239 public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow) {
1234 1240 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel());
1235 1241 +
1236 1242 + if (this.player.isImmobile()) return; // CraftBukkit
1237 1243 + CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit
1238 1244 +
1239 1245 this.player.doCloseContainer();
1240 1246 }
1241 1247
1529 1535 + if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) {
1530 1536 + // Need to update the inventory on crafting to
1531 1537 + // correctly support custom recipes
1532 1538 + player.containerMenu.sendAllDataToRemote();
1533 1539 + }
1534 1540 + }
1535 1541 + // CraftBukkit end
1536 1542 ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packetplayinwindowclick.getChangedSlots()).iterator();
1537 1543
1538 1544 while (objectiterator.hasNext()) {
1539 -@@ -1456,6 +2478,7 @@
1545 +@@ -1456,6 +2484,7 @@
1540 1546 @Override
1541 1547 public void handleContainerButtonClick(PacketPlayInEnchantItem packetplayinenchantitem) {
1542 1548 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinenchantitem, this, this.player.getLevel());
1543 1549 + if (this.player.isImmobile()) return; // CraftBukkit
1544 1550 this.player.resetLastActionTime();
1545 1551 if (this.player.containerMenu.containerId == packetplayinenchantitem.getContainerId() && !this.player.isSpectator()) {
1546 1552 this.player.containerMenu.clickMenuButton(this.player, packetplayinenchantitem.getButtonId());
1547 -@@ -1483,6 +2506,43 @@
1553 +@@ -1483,6 +2512,43 @@
1548 1554
1549 1555 boolean flag1 = packetplayinsetcreativeslot.getSlotNum() >= 1 && packetplayinsetcreativeslot.getSlotNum() <= 45;
1550 1556 boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty();
1551 1557 + if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem(), packetplayinsetcreativeslot.getItem()))) { // Insist on valid slot
1552 1558 + // CraftBukkit start - Call click event
1553 1559 + InventoryView inventory = this.player.inventoryMenu.getBukkitView();
1554 1560 + org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.getItem());
1555 1561 +
1556 1562 + SlotType type = SlotType.QUICKBAR;
1557 1563 + if (flag) {
1581 1587 + this.player.connection.send(new PacketPlayOutSetSlot(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinsetcreativeslot.getSlotNum(), this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem()));
1582 1588 + this.player.connection.send(new PacketPlayOutSetSlot(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY));
1583 1589 + }
1584 1590 + return;
1585 1591 + }
1586 1592 + }
1587 1593 + // CraftBukkit end
1588 1594
1589 1595 if (flag1 && flag2) {
1590 1596 this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).set(itemstack);
1591 -@@ -1505,6 +2565,7 @@
1597 +@@ -1505,6 +2571,7 @@
1592 1598 }
1593 1599
1594 1600 private void updateSignText(PacketPlayInUpdateSign packetplayinupdatesign, List<ITextFilter.a> list) {
1595 1601 + if (this.player.isImmobile()) return; // CraftBukkit
1596 1602 this.player.resetLastActionTime();
1597 1603 WorldServer worldserver = this.player.getLevel();
1598 1604 BlockPosition blockposition = packetplayinupdatesign.getPos();
1599 -@@ -1521,18 +2582,37 @@
1605 +@@ -1521,18 +2588,37 @@
1600 1606
1601 1607 if (!tileentitysign.isEditable() || !this.player.getUUID().equals(tileentitysign.getPlayerWhoMayEdit())) {
1602 1608 PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString());
1603 1609 + this.send(tileentity.getUpdatePacket()); // CraftBukkit
1604 1610 return;
1605 1611 }
1606 1612
1607 1613 + // CraftBukkit start
1608 1614 + Player player = this.player.getBukkitEntity();
1609 1615 + int x = packetplayinupdatesign.getPos().getX();
1629 1635 + IChatBaseComponent[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines());
1630 1636 + for (int i = 0; i < components.length; i++) {
1631 1637 + tileentitysign.setMessage(i, components[i]);
1632 1638 }
1633 1639 + tileentitysign.isEditable = false;
1634 1640 }
1635 1641 + // CraftBukkit end
1636 1642
1637 1643 tileentitysign.setChanged();
1638 1644 worldserver.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3);
1639 -@@ -1542,6 +2622,7 @@
1645 +@@ -1542,6 +2628,7 @@
1640 1646
1641 1647 @Override
1642 1648 public void handleKeepAlive(PacketPlayInKeepAlive packetplayinkeepalive) {
1643 1649 + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinkeepalive, this, this.player.getLevel()); // CraftBukkit
1644 1650 if (this.keepAlivePending && packetplayinkeepalive.getId() == this.keepAliveChallenge) {
1645 1651 int i = (int) (SystemUtils.getMillis() - this.keepAliveTime);
1646 1652
1647 -@@ -1556,7 +2637,17 @@
1653 +@@ -1556,7 +2643,17 @@
1648 1654 @Override
1649 1655 public void handlePlayerAbilities(PacketPlayInAbilities packetplayinabilities) {
1650 1656 PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinabilities, this, this.player.getLevel());
1651 1657 - this.player.getAbilities().flying = packetplayinabilities.isFlying() && this.player.getAbilities().mayfly;
1652 1658 + // CraftBukkit start
1653 1659 + if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packetplayinabilities.isFlying()) {
1654 1660 + PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packetplayinabilities.isFlying());
1655 1661 + this.cserver.getPluginManager().callEvent(event);
1656 1662 + if (!event.isCancelled()) {
1657 1663 + this.player.getAbilities().flying = packetplayinabilities.isFlying(); // Actually set the player's flying status
1658 1664 + } else {
1659 1665 + this.player.onUpdateAbilities(); // Tell the player their ability was reverted
1660 1666 + }
1661 1667 + }
1662 1668 + // CraftBukkit end
1663 1669 }
1664 1670
1665 1671 @Override
1666 -@@ -1565,8 +2656,50 @@
1672 +@@ -1565,8 +2662,50 @@
1667 1673 this.player.updateOptions(packetplayinsettings);
1668 1674 }
1669 1675
1670 1676 - @Override
1671 1677 - public void handleCustomPayload(PacketPlayInCustomPayload packetplayincustompayload) {}
1672 1678 + // CraftBukkit start
1673 1679 + private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register");
1674 1680 + private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister");
1675 1681 +
1676 1682 + @Override

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

Add shortcut