Commits
md_5 authored 8e5e90d5eba
63 63 | private final IntHashMap<Short> k = new IntHashMap(); |
64 64 | private double l; |
65 65 | |
66 66 | private int E; |
67 67 | private int F; |
68 68 | private int G; |
69 69 | + private boolean processedDisconnect; // CraftBukkit - Added |
70 70 | |
71 71 | public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { |
72 72 | this.minecraftServer = minecraftserver; |
73 - | |
73 + | |
74 74 | networkmanager.setPacketListener(this); |
75 75 | this.player = entityplayer; |
76 76 | entityplayer.playerConnection = this; |
77 77 | + |
78 78 | + // CraftBukkit start - add fields and methods |
79 79 | + this.server = minecraftserver.server; |
80 80 | + } |
81 81 | + |
82 82 | + private final org.bukkit.craftbukkit.CraftServer server; |
83 83 | + private int lastTick = MinecraftServer.currentTick; |
95 95 | + private float lastYaw = Float.MAX_VALUE; |
96 96 | + private boolean justTeleported = false; |
97 97 | + |
98 98 | + public CraftPlayer getPlayer() { |
99 99 | + return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); |
100 100 | } |
101 101 | + private final static HashSet<Integer> invalidItems = new HashSet<Integer>(java.util.Arrays.asList(8, 9, 10, 11, 26, 34, 36, 43, 51, 52, 55, 59, 60, 62, 63, 64, 68, 71, 74, 75, 83, 90, 92, 93, 94, 104, 105, 115, 117, 118, 119, 125, 127, 132, 140, 141, 142, 144)); // TODO: Check after every update. |
102 102 | + // CraftBukkit end |
103 103 | |
104 104 | public void E_() { |
105 - | this.d(); |
106 - | |
105 + | - this.d(); |
106 + | + // CraftBukkit start - SPIGOT-1903: reverse order of location update |
107 + | this.player.k_(); |
108 + | + this.d(); |
109 + | + // CraftBukkit end |
110 + | this.player.setLocation(this.l, this.m, this.n, this.player.yaw, this.player.pitch); |
111 + | ++this.e; |
112 + | this.G = this.F; |
113 + | |
107 114 | } |
108 115 | |
109 116 | this.minecraftServer.methodProfiler.b(); |
110 117 | + // CraftBukkit start |
111 118 | + for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; |
112 119 | + /* Use thread-safe field access instead |
113 120 | if (this.chatThrottle > 0) { |
114 121 | --this.chatThrottle; |
115 122 | } |
116 123 | + */ |
117 124 | + // CraftBukkit end |
118 125 | |
119 126 | if (this.j > 0) { |
120 127 | --this.j; |
121 128 | } |
122 129 | |
123 130 | if (this.player.I() > 0L && this.minecraftServer.getIdleTimeout() > 0 && MinecraftServer.av() - this.player.I() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { |
124 131 | + this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 |
125 132 | this.disconnect("You have been idle for too long!"); |
126 133 | } |
127 134 | |
128 - | |
135 + | |
129 136 | } |
130 137 | |
131 138 | public void disconnect(String s) { |
132 139 | + // CraftBukkit start - fire PlayerKickEvent |
133 140 | + if (this.processedDisconnect) { |
134 141 | + return; |
135 142 | + } |
136 143 | + String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; |
137 144 | + |
138 145 | + PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); |
162 169 | + // CraftBukkit - Don't wait |
163 170 | + this.minecraftServer.postToMainThread(new Runnable() { |
164 171 | public void run() { |
165 172 | PlayerConnection.this.networkManager.handleDisconnection(); |
166 173 | } |
167 174 | - })); |
168 175 | + }); |
169 176 | } |
170 177 | |
171 178 | public void a(PacketPlayInSteerVehicle packetplayinsteervehicle) { |
172 - | |
179 + | |
173 180 | double d9 = entity.motX * entity.motX + entity.motY * entity.motY + entity.motZ * entity.motZ; |
174 181 | double d10 = d6 * d6 + d7 * d7 + d8 * d8; |
175 182 | |
176 183 | - if (d10 - d9 > 100.0D && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(entity.getName()))) { |
177 184 | + |
178 185 | + // CraftBukkit start - handle custom speeds and skipped ticks |
179 186 | + this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; |
180 187 | + this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); |
181 188 | + this.lastTick = (int) (System.currentTimeMillis() / 50); |
182 189 | + |
198 205 | + } else { |
199 206 | + speed = player.abilities.walkSpeed * 10f; |
200 207 | + } |
201 208 | + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player |
202 209 | + |
203 210 | + if (d10 - d9 > Math.max(100, Math.pow((double) (10.0F * (float) i * speed), 2)) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(entity.getName()))) { |
204 211 | + // CraftBukkit end |
205 212 | PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[] { entity.getName(), this.player.getName(), Double.valueOf(d6), Double.valueOf(d7), Double.valueOf(d8)}); |
206 213 | this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); |
207 214 | return; |
208 - | |
215 + | |
209 216 | return; |
210 217 | } |
211 218 | |
212 219 | + // CraftBukkit start - fire PlayerMoveEvent |
213 220 | + Player player = this.getPlayer(); |
214 221 | + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. |
215 222 | + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. |
216 223 | + |
217 224 | + // If the packet contains movement information then we update the To location with the correct XYZ. |
218 225 | + to.setX(packetplayinvehiclemove.getX()); |
261 268 | + this.justTeleported = false; |
262 269 | + return; |
263 270 | + } |
264 271 | + } |
265 272 | + } |
266 273 | + // CraftBukkit end |
267 274 | + |
268 275 | this.minecraftServer.getPlayerList().d(this.player); |
269 276 | this.player.checkMovement(this.player.locX - d0, this.player.locY - d1, this.player.locZ - d2); |
270 277 | this.D = d11 >= -0.03125D && !this.minecraftServer.getAllowFlight() && !worldserver.d(entity.getBoundingBox().g(0.0625D).a(0.0D, -0.55D, 0.0D)); |
271 - | |
278 + | |
272 279 | } else { |
273 280 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
274 281 | |
275 282 | - if (!this.player.viewingCredits) { |
276 283 | + if (!this.player.viewingCredits && !this.player.cj()) { // CraftBukkit // PAIL: rename |
277 284 | if (this.e == 0) { |
278 285 | this.d(); |
279 286 | } |
280 - | |
287 + | |
281 288 | this.A = this.e; |
282 289 | this.a(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); |
283 290 | } |
284 291 | - |
285 292 | + this.allowedPlayerTicks = 20; // CraftBukkit |
286 293 | } else { |
287 294 | this.A = this.e; |
288 295 | if (this.player.isPassenger()) { |
289 296 | this.player.setLocation(this.player.locX, this.player.locY, this.player.locZ, packetplayinflying.a(this.player.yaw), packetplayinflying.b(this.player.pitch)); |
290 297 | this.minecraftServer.getPlayerList().d(this.player); |
293 300 | + // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify |
294 301 | + double prevX = player.locX; |
295 302 | + double prevY = player.locY; |
296 303 | + double prevZ = player.locZ; |
297 304 | + float prevYaw = player.yaw; |
298 305 | + float prevPitch = player.pitch; |
299 306 | + // CraftBukkit end |
300 307 | double d0 = this.player.locX; |
301 308 | double d1 = this.player.locY; |
302 309 | double d2 = this.player.locZ; |
303 - | |
310 + | |
304 311 | ++this.F; |
305 312 | int i = this.F - this.G; |
306 313 | |
307 314 | - if (i > 5) { |
308 315 | - PlayerConnection.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", new Object[] { this.player.getName(), Integer.valueOf(i)}); |
309 316 | + // CraftBukkit start - handle custom speeds and skipped ticks |
310 317 | + this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; |
311 318 | + this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); |
312 319 | + this.lastTick = (int) (System.currentTimeMillis() / 50); |
313 320 | + |
330 337 | + |
331 338 | if (!this.player.K() && (!this.player.x().getGameRules().getBoolean("disableElytraMovementCheck") || !this.player.cG())) { |
332 339 | float f2 = this.player.cG() ? 300.0F : 100.0F; |
333 340 | |
334 341 | - if (d11 - d10 > (double) (f2 * (float) i) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(this.player.getName()))) { |
335 342 | + if (d11 - d10 > Math.max(100, Math.pow((double) (10.0F * (float) i * speed), 2)) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(this.player.getName()))) { |
336 343 | + // CraftBukkit end |
337 344 | PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[] { this.player.getName(), Double.valueOf(d7), Double.valueOf(d8), Double.valueOf(d9)}); |
338 345 | this.a(this.player.locX, this.player.locY, this.player.locZ, this.player.yaw, this.player.pitch); |
339 346 | return; |
340 - | |
347 + | |
341 348 | } |
342 349 | } |
343 350 | |
344 351 | + // CraftBukkit start - fire PlayerMoveEvent |
345 352 | + // Rest to old location first |
346 353 | + this.player.setLocation(prevX, prevY, prevZ, prevYaw, prevPitch); |
347 354 | + |
348 355 | + Player player = this.getPlayer(); |
349 356 | + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. |
350 357 | + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. |
400 407 | + return; |
401 408 | + } |
402 409 | + } |
403 410 | + } |
404 411 | + this.player.setLocation(d4, d5, d6, f, f1); // Copied from above |
405 412 | + // CraftBukkit end |
406 413 | + |
407 414 | this.B = d12 >= -0.03125D; |
408 415 | this.B &= !this.minecraftServer.getAllowFlight() && !this.player.abilities.canFly; |
409 416 | this.B &= !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.cG() && !worldserver.d(this.player.getBoundingBox().g(0.0625D).a(0.0D, -0.55D, 0.0D)); |
410 - | |
417 + | |
411 418 | } |
412 419 | |
413 420 | public void a(double d0, double d1, double d2, float f, float f1) { |
414 421 | - this.a(d0, d1, d2, f, f1, Collections.emptySet()); |
415 422 | + this.a(d0, d1, d2, f, f1, Collections.<PacketPlayOutPosition.EnumPlayerTeleportFlags>emptySet()); |
416 423 | } |
417 424 | |
418 425 | public void a(double d0, double d1, double d2, float f, float f1, Set<PacketPlayOutPosition.EnumPlayerTeleportFlags> set) { |
419 426 | - double d3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X) ? this.player.locX : 0.0D; |
420 427 | - double d4 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y) ? this.player.locY : 0.0D; |
485 492 | + this.teleportPos = this.teleportPos.add(0.0D, this.player.locY, 0.0D); |
486 493 | + } |
487 494 | + |
488 495 | + if (set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Z)) { |
489 496 | + this.teleportPos = this.teleportPos.add(0.0D, 0.0D, this.player.locZ); |
490 497 | + } |
491 498 | + // CraftBukkit end |
492 499 | float f2 = f; |
493 500 | float f3 = f1; |
494 501 | |
495 - | |
502 + | |
496 503 | f3 = f1 + this.player.pitch; |
497 504 | } |
498 505 | |
499 506 | + // CraftBukkit start - update last location |
500 507 | + this.lastPosX = this.teleportPos.x; |
501 508 | + this.lastPosY = this.teleportPos.y; |
502 509 | + this.lastPosZ = this.teleportPos.z; |
503 510 | + this.lastYaw = f2; |
504 511 | + this.lastPitch = f3; |
505 512 | + // CraftBukkit end |
506 513 | + |
507 514 | if (++this.teleportAwait == Integer.MAX_VALUE) { |
508 515 | this.teleportAwait = 0; |
509 516 | } |
510 - | |
517 + | |
511 518 | |
512 519 | public void a(PacketPlayInBlockDig packetplayinblockdig) { |
513 520 | PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.x()); |
514 521 | + if (this.player.cj()) return; // CraftBukkit |
515 522 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
516 523 | BlockPosition blockposition = packetplayinblockdig.a(); |
517 524 | |
518 525 | this.player.resetIdleTimer(); |
519 526 | ItemStack itemstack; |
520 527 | |
568 575 | this.player.a(true); |
569 576 | } |
570 577 | |
571 578 | return; |
572 579 | |
573 580 | - case 4: |
574 581 | + case 4: // RELEASE_USE_ITEM |
575 582 | this.player.clearActiveItem(); |
576 583 | itemstack = this.player.getItemInMainHand(); |
577 584 | if (itemstack != null && itemstack.count == 0) { |
578 - | |
585 + | |
579 586 | |
580 587 | return; |
581 588 | |
582 589 | - case 5: |
583 590 | - case 6: |
584 591 | - case 7: |
585 592 | + case 5: // START_DESTROY_BLOCK |
586 593 | + case 6: // ABORT_DESTROY_BLOCK |
587 594 | + case 7: // STOP_DESTROY_BLOCK |
588 595 | double d0 = this.player.locX - ((double) blockposition.getX() + 0.5D); |
589 596 | double d1 = this.player.locY - ((double) blockposition.getY() + 0.5D) + 1.5D; |
590 597 | double d2 = this.player.locZ - ((double) blockposition.getZ() + 0.5D); |
591 - | |
598 + | |
592 599 | if (!this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) { |
593 600 | this.player.playerInteractManager.a(blockposition, packetplayinblockdig.b()); |
594 601 | } else { |
595 602 | + // CraftBukkit start - fire PlayerInteractEvent |
596 603 | + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, packetplayinblockdig.b(), this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); |
597 604 | this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); |
598 605 | + // Update any tile entity data for this block |
599 606 | + TileEntity tileentity = worldserver.getTileEntity(blockposition); |
600 607 | + if (tileentity != null) { |
601 608 | + this.player.playerConnection.sendPacket(tileentity.getUpdatePacket()); |
602 609 | + } |
603 610 | + // CraftBukkit end |
604 611 | } |
605 612 | } else { |
606 613 | if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { |
607 - | |
614 + | |
608 615 | default: |
609 616 | throw new IllegalArgumentException("Invalid player action"); |
610 617 | } |
611 618 | + // CraftBukkit end |
612 619 | } |
613 620 | |
614 621 | public void a(PacketPlayInUseItem packetplayinuseitem) { |
615 622 | PlayerConnectionUtils.ensureMainThread(packetplayinuseitem, this, this.player.x()); |
616 623 | + if (this.player.cj()) return; // CraftBukkit |
617 624 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
618 625 | EnumHand enumhand = packetplayinuseitem.c(); |
619 626 | ItemStack itemstack = this.player.b(enumhand); |
620 - | |
627 + | |
621 628 | chatmessage.getChatModifier().setColor(EnumChatFormat.RED); |
622 629 | this.player.playerConnection.sendPacket(new PacketPlayOutChat(chatmessage)); |
623 630 | } else if (this.teleportPos == null && 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)) { |
624 631 | + // CraftBukkit start - Check if we can actually do something over this large a distance |
625 632 | + Location eyeLoc = this.getPlayer().getEyeLocation(); |
626 633 | + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); |
627 634 | + if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { |
628 635 | + return; |
629 636 | + } |
630 637 | + // CraftBukkit end |
631 638 | this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, blockposition, enumdirection, packetplayinuseitem.d(), packetplayinuseitem.e(), packetplayinuseitem.f()); |
632 639 | } |
633 640 | |
634 - | |
641 + | |
635 642 | |
636 643 | public void a(PacketPlayInBlockPlace packetplayinblockplace) { |
637 644 | PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.x()); |
638 645 | + if (this.player.cj()) return; // CraftBukkit |
639 646 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
640 647 | EnumHand enumhand = packetplayinblockplace.a(); |
641 648 | ItemStack itemstack = this.player.b(enumhand); |
642 649 | |
643 650 | this.player.resetIdleTimer(); |
644 651 | if (itemstack != null) { |
685 692 | + itemstack = this.player.b(enumhand); |
686 693 | + if (itemstack != null && itemstack.count == 0) { |
687 694 | + this.player.a(enumhand, (ItemStack) null); |
688 695 | + itemstack = null; |
689 696 | + } |
690 697 | + } |
691 698 | + // CraftBukkit end |
692 699 | } |
693 700 | } |
694 701 | |
695 - | |
702 + | |
696 703 | WorldServer[] aworldserver = this.minecraftServer.worldServer; |
697 704 | int i = aworldserver.length; |
698 705 | |
699 706 | - for (int j = 0; j < i; ++j) { |
700 707 | - WorldServer worldserver = aworldserver[j]; |
701 708 | + // CraftBukkit - use the worlds array list |
702 709 | + for (WorldServer worldserver : minecraftServer.worlds) { |
703 710 | |
704 711 | if (worldserver != null) { |
705 712 | entity = packetplayinspectate.a(worldserver); |
706 - | |
713 + | |
707 714 | if (entity != null) { |
708 715 | this.player.setSpectatorTarget(this.player); |
709 716 | this.player.stopRiding(); |
710 717 | + |
711 718 | + /* CraftBukkit start - replace with bukkit handling for multi-world |
712 719 | if (entity.world == this.player.world) { |
713 720 | this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ); |
714 721 | } else { |
715 - | |
722 + | |
716 723 | this.minecraftServer.getPlayerList().b(this.player, worldserver2); |
717 724 | this.minecraftServer.getPlayerList().updateClient(this.player); |
718 725 | } |
719 726 | + */ |
720 727 | + this.player.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE); |
721 728 | + // CraftBukkit end |
722 729 | } |
723 730 | } |
724 731 | |
725 732 | } |
726 733 | |
727 734 | - public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) {} |
728 735 | + // CraftBukkit start |
729 736 | + public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { |
730 737 | + this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); |
731 738 | + } |
732 739 | + // CraftBukkit end |
733 740 | |
734 741 | public void a(PacketPlayInBoatMove packetplayinboatmove) { |
735 742 | PlayerConnectionUtils.ensureMainThread(packetplayinboatmove, this, this.player.x()); |
736 - | |
743 + | |
737 744 | } |
738 745 | |
739 746 | public void a(IChatBaseComponent ichatbasecomponent) { |
740 747 | - PlayerConnection.LOGGER.info("{} lost connection: {}", new Object[] { this.player.getName(), ichatbasecomponent}); |
741 748 | + // CraftBukkit start - Rarely it would send a disconnect line twice |
742 749 | + if (this.processedDisconnect) { |
743 750 | + return; |
744 751 | + } else { |
745 752 | + this.processedDisconnect = true; |
746 753 | + } |
758 765 | this.player.t(); |
759 766 | - this.minecraftServer.getPlayerList().disconnect(this.player); |
760 767 | + String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); |
761 768 | + if ((quitMessage != null) && (quitMessage.length() > 0)) { |
762 769 | + this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); |
763 770 | + } |
764 771 | + // CraftBukkit end |
765 772 | if (this.minecraftServer.R() && this.player.getName().equals(this.minecraftServer.Q())) { |
766 773 | PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out"); |
767 774 | this.minecraftServer.safeShutdown(); |
768 - | |
775 + | |
769 776 | } |
770 777 | } |
771 778 | |
772 779 | + // CraftBukkit start |
773 780 | + if (packet == null) { |
774 781 | + return; |
775 782 | + } else if (packet instanceof PacketPlayOutSpawnPosition) { |
776 783 | + PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet; |
777 784 | + this.player.compassTarget = new Location(this.getPlayer().getWorld(), packet6.position.getX(), packet6.position.getY(), packet6.position.getZ()); |
778 785 | + } |
779 786 | + // CraftBukkit end |
780 787 | + |
781 788 | try { |
782 789 | this.networkManager.sendPacket(packet); |
783 790 | } catch (Throwable throwable) { |
784 - | |
791 + | |
785 792 | |
786 793 | public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) { |
787 794 | PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.x()); |
788 795 | + if (this.player.cj()) return; // CraftBukkit |
789 796 | if (packetplayinhelditemslot.a() >= 0 && packetplayinhelditemslot.a() < PlayerInventory.getHotbarSize()) { |
790 797 | + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.a()); |
791 798 | + this.server.getPluginManager().callEvent(event); |
792 799 | + if (event.isCancelled()) { |
793 800 | + this.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); |
794 801 | + this.player.resetIdleTimer(); |
809 816 | + // CraftBukkit start - async chat |
810 817 | + boolean isSync = packetplayinchat.a().startsWith("/"); |
811 818 | + if (packetplayinchat.a().startsWith("/")) { |
812 819 | + PlayerConnectionUtils.ensureMainThread(packetplayinchat, this, this.player.x()); |
813 820 | + } |
814 821 | + // CraftBukkit end |
815 822 | + if (this.player.dead || this.player.getChatFlags() == EntityHuman.EnumChatVisibility.HIDDEN) { // CraftBukkit - dead men tell no tales |
816 823 | ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]); |
817 824 | |
818 825 | chatmessage.getChatModifier().setColor(EnumChatFormat.RED); |
819 - | |
826 + | |
820 827 | |
821 828 | for (int i = 0; i < s.length(); ++i) { |
822 829 | if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) { |
823 830 | - this.disconnect("Illegal characters in chat"); |
824 831 | + // CraftBukkit start - threadsafety |
825 832 | + if (!isSync) { |
826 833 | + Waitable waitable = new Waitable() { |
827 834 | + @Override |
828 835 | + protected Object evaluate() { |
829 836 | + PlayerConnection.this.disconnect("Illegal characters in chat"); |
1067 1074 | + |
1068 1075 | + if (e2.isCancelled()) { |
1069 1076 | + return; |
1070 1077 | + } |
1071 1078 | + break; |
1072 1079 | + } |
1073 1080 | + // CraftBukkit end |
1074 1081 | this.player.resetIdleTimer(); |
1075 1082 | IJumpable ijumpable; |
1076 1083 | |
1077 - | |
1084 + | |
1078 1085 | |
1079 1086 | public void a(PacketPlayInUseEntity packetplayinuseentity) { |
1080 1087 | PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.x()); |
1081 1088 | + if (this.player.cj()) return; // CraftBukkit |
1082 1089 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
1083 1090 | Entity entity = packetplayinuseentity.a((World) worldserver); |
1084 1091 | |
1085 - | |
1092 + | |
1086 1093 | EnumHand enumhand; |
1087 1094 | ItemStack itemstack; |
1088 1095 | |
1089 1096 | + ItemStack itemInHand = this.player.b(packetplayinuseentity.b() == null ? EnumHand.MAIN_HAND : packetplayinuseentity.b()); // CraftBukkit |
1090 1097 | + |
1091 1098 | + if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT |
1092 1099 | + || packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { |
1093 1100 | + // CraftBukkit start |
1094 1101 | + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; |
1095 1102 | + Item origItem = this.player.inventory.getItemInHand() == null ? null : this.player.inventory.getItemInHand().getItem(); |
1149 1156 | this.player.attack(entity); |
1150 1157 | + |
1151 1158 | + // CraftBukkit start |
1152 1159 | + if (itemInHand != null && itemInHand.count <= -1) { |
1153 1160 | + this.player.updateInventory(this.player.activeContainer); |
1154 1161 | + } |
1155 1162 | + // CraftBukkit end |
1156 1163 | } |
1157 1164 | } |
1158 1165 | } |
1159 - | |
1166 + | |
1160 1167 | case 1: |
1161 1168 | if (this.player.viewingCredits) { |
1162 1169 | this.player.viewingCredits = false; |
1163 1170 | - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true); |
1164 1171 | + // this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true); |
1165 1172 | + this.minecraftServer.getPlayerList().changeDimension(this.player, 0, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management |
1166 1173 | } else { |
1167 1174 | if (this.player.getHealth() > 0.0F) { |
1168 1175 | return; |
1169 - | |
1176 + | |
1170 1177 | |
1171 1178 | public void a(PacketPlayInCloseWindow packetplayinclosewindow) { |
1172 1179 | PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.x()); |
1173 1180 | + |
1174 1181 | + if (this.player.cj()) return; // CraftBukkit |
1175 1182 | + CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit |
1176 1183 | + |
1177 1184 | this.player.s(); |
1178 1185 | } |
1179 1186 | |
1180 1187 | public void a(PacketPlayInWindowClick packetplayinwindowclick) { |
1181 1188 | PlayerConnectionUtils.ensureMainThread(packetplayinwindowclick, this, this.player.x()); |
1182 1189 | + if (this.player.cj()) return; // CraftBukkit |
1183 1190 | this.player.resetIdleTimer(); |
1184 1191 | if (this.player.activeContainer.windowId == packetplayinwindowclick.a() && this.player.activeContainer.c(this.player)) { |
1185 1192 | - if (this.player.isSpectator()) { |
1186 1193 | + boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if |
1187 1194 | + if (false/*this.player.isSpectator()*/) { // CraftBukkit |
1188 1195 | ArrayList arraylist = Lists.newArrayList(); |
1189 1196 | |
1190 1197 | for (int i = 0; i < this.player.activeContainer.c.size(); ++i) { |
1191 - | |
1198 + | |
1192 1199 | |
1193 1200 | this.player.a(this.player.activeContainer, (List) arraylist); |
1194 1201 | } else { |
1195 1202 | - ItemStack itemstack = this.player.activeContainer.a(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player); |
1196 1203 | + // CraftBukkit start - Call InventoryClickEvent |
1197 1204 | + if (packetplayinwindowclick.b() < -1 && packetplayinwindowclick.b() != -999) { |
1198 1205 | + return; |
1199 1206 | + } |
1200 1207 | + |
1201 1208 | + InventoryView inventory = this.player.activeContainer.getBukkitView(); |
1202 1209 | + SlotType type = CraftInventoryView.getSlotType(inventory, packetplayinwindowclick.b()); |
1203 - | |
1210 + | + |
1204 1211 | + InventoryClickEvent event; |
1205 1212 | + ClickType click = ClickType.UNKNOWN; |
1206 1213 | + InventoryAction action = InventoryAction.UNKNOWN; |
1207 1214 | + |
1208 1215 | + ItemStack itemstack = null; |
1209 1216 | + |
1210 1217 | + switch (packetplayinwindowclick.f()) { |
1211 1218 | + case PICKUP: |
1212 1219 | + if (packetplayinwindowclick.c() == 0) { |
1213 1220 | + click = ClickType.LEFT; |
1369 1376 | + action = InventoryAction.NOTHING; |
1370 1377 | + // Quick check for if we have any of the item |
1371 1378 | + if (inventory.getTopInventory().contains(org.bukkit.Material.getMaterial(Item.getId(cursor.getItem()))) || inventory.getBottomInventory().contains(org.bukkit.Material.getMaterial(Item.getId(cursor.getItem())))) { |
1372 1379 | + action = InventoryAction.COLLECT_TO_CURSOR; |
1373 1380 | + } |
1374 1381 | + } |
1375 1382 | + break; |
1376 1383 | + default: |
1377 1384 | + break; |
1378 1385 | + } |
1379 - | + |
1386 + | |
1380 1387 | + if (packetplayinwindowclick.f() != InventoryClickType.QUICK_CRAFT) { |
1381 1388 | + if (click == ClickType.NUMBER_KEY) { |
1382 1389 | + event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.b(), click, action, packetplayinwindowclick.c()); |
1383 1390 | + } else { |
1384 1391 | + event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.b(), click, action); |
1385 1392 | + } |
1386 1393 | + |
1387 1394 | + org.bukkit.inventory.Inventory top = inventory.getTopInventory(); |
1388 1395 | + if (packetplayinwindowclick.b() == 0 && top instanceof CraftingInventory) { |
1389 1396 | + org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); |
1462 1469 | + if (event instanceof CraftItemEvent) { |
1463 1470 | + // Need to update the inventory on crafting to |
1464 1471 | + // correctly support custom recipes |
1465 1472 | + player.updateInventory(player.activeContainer); |
1466 1473 | + } |
1467 1474 | + } |
1468 1475 | + // CraftBukkit end |
1469 1476 | if (ItemStack.matches(packetplayinwindowclick.e(), itemstack)) { |
1470 1477 | this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), true)); |
1471 1478 | this.player.f = true; |
1472 - | |
1479 + | |
1473 1480 | |
1474 1481 | public void a(PacketPlayInEnchantItem packetplayinenchantitem) { |
1475 1482 | PlayerConnectionUtils.ensureMainThread(packetplayinenchantitem, this, this.player.x()); |
1476 1483 | + if (this.player.cj()) return; // CraftBukkit |
1477 1484 | this.player.resetIdleTimer(); |
1478 1485 | if (this.player.activeContainer.windowId == packetplayinenchantitem.a() && this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { |
1479 1486 | this.player.activeContainer.a(this.player, packetplayinenchantitem.b()); |
1480 - | |
1487 + | |
1481 1488 | } |
1482 1489 | |
1483 1490 | boolean flag1 = packetplayinsetcreativeslot.a() >= 1 && packetplayinsetcreativeslot.a() <= 45; |
1484 1491 | - boolean flag2 = itemstack == null || itemstack.getItem() != null; |
1485 1492 | + // CraftBukkit - Add invalidItems check |
1486 1493 | + boolean flag2 = itemstack == null || itemstack.getItem() != null && !invalidItems.contains(Item.getId(itemstack.getItem())); |
1487 1494 | boolean flag3 = itemstack == null || itemstack.getData() >= 0 && itemstack.count <= 64 && itemstack.count > 0; |
1488 1495 | + // CraftBukkit start - Call click event |
1489 1496 | + if (flag || (flag1 && !ItemStack.matches(this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem(), packetplayinsetcreativeslot.getItemStack()))) { // Insist on valid slot |
1490 1497 | + |
1520 1527 | + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.defaultContainer.windowId, packetplayinsetcreativeslot.a(), this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem())); |
1521 1528 | + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, null)); |
1522 1529 | + } |
1523 1530 | + return; |
1524 1531 | + } |
1525 1532 | + } |
1526 1533 | + // CraftBukkit end |
1527 1534 | |
1528 1535 | if (flag1 && flag2 && flag3) { |
1529 1536 | if (itemstack == null) { |
1530 - | |
1537 + | |
1531 1538 | |
1532 1539 | public void a(PacketPlayInTransaction packetplayintransaction) { |
1533 1540 | PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.x()); |
1534 1541 | + if (this.player.cj()) return; // CraftBukkit |
1535 1542 | Short oshort = (Short) this.k.get(this.player.activeContainer.windowId); |
1536 1543 | |
1537 1544 | if (oshort != null && packetplayintransaction.b() == oshort.shortValue() && this.player.activeContainer.windowId == packetplayintransaction.a() && !this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { |
1538 - | |
1545 + | |
1539 1546 | |
1540 1547 | public void a(PacketPlayInUpdateSign packetplayinupdatesign) { |
1541 1548 | PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.x()); |
1542 1549 | + if (this.player.cj()) return; // CraftBukkit |
1543 1550 | this.player.resetIdleTimer(); |
1544 1551 | WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); |
1545 1552 | BlockPosition blockposition = packetplayinupdatesign.a(); |
1546 - | |
1553 + | |
1547 1554 | |
1548 1555 | if (!tileentitysign.d() || tileentitysign.e() != this.player) { |
1549 1556 | this.minecraftServer.warning("Player " + this.player.getName() + " just tried to change non-editable sign"); |
1550 1557 | + this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit |
1551 1558 | return; |
1552 1559 | } |
1553 1560 | |
1554 1561 | String[] astring = packetplayinupdatesign.b(); |
1555 1562 | |
1556 1563 | + // CraftBukkit start |
1568 1575 | + this.server.getPluginManager().callEvent(event); |
1569 1576 | + |
1570 1577 | + if (!event.isCancelled()) { |
1571 1578 | + System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); |
1572 1579 | + tileentitysign.isEditable = false; |
1573 1580 | + } |
1574 1581 | + // CraftBukkit end |
1575 1582 | |
1576 1583 | tileentitysign.update(); |
1577 1584 | worldserver.notify(blockposition, iblockdata, iblockdata, 3); |
1578 - | |
1585 + | |
1579 1586 | |
1580 1587 | public void a(PacketPlayInAbilities packetplayinabilities) { |
1581 1588 | PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.x()); |
1582 1589 | - this.player.abilities.isFlying = packetplayinabilities.isFlying() && this.player.abilities.canFly; |
1583 1590 | + // CraftBukkit start |
1584 1591 | + if (this.player.abilities.canFly && this.player.abilities.isFlying != packetplayinabilities.isFlying()) { |
1585 1592 | + PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.server.getPlayer(this.player), packetplayinabilities.isFlying()); |
1586 1593 | + this.server.getPluginManager().callEvent(event); |
1587 1594 | + if (!event.isCancelled()) { |
1588 1595 | + this.player.abilities.isFlying = packetplayinabilities.isFlying(); // Actually set the player's flying status |
1597 1604 | PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.x()); |
1598 1605 | + // CraftBukkit start |
1599 1606 | + if (chatSpamField.addAndGet(this, 10) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { |
1600 1607 | + this.disconnect("disconnect.spam"); |
1601 1608 | + return; |
1602 1609 | + } |
1603 1610 | + // CraftBukkit end |
1604 1611 | ArrayList arraylist = Lists.newArrayList(); |
1605 1612 | Iterator iterator = this.minecraftServer.tabCompleteCommand(this.player, packetplayintabcomplete.a(), packetplayintabcomplete.b(), packetplayintabcomplete.c()).iterator(); |
1606 1613 | |
1607 - | |
1614 + | |
1608 1615 | } |
1609 1616 | |
1610 1617 | if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack.getItem() == itemstack1.getItem()) { |
1611 1618 | + itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit |
1612 1619 | itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); |
1613 1620 | + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit |
1614 1621 | } |
1615 1622 | } catch (Exception exception) { |
1616 1623 | PlayerConnection.LOGGER.error("Couldn\'t handle book info", exception); |
1617 1624 | + this.disconnect("Invalid book data!"); // CraftBukkit |
1618 1625 | } |
1619 1626 | } else { |
1620 1627 | String s1; |
1621 - | |
1628 + | |
1622 1629 | } |
1623 1630 | |
1624 1631 | if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) { |
1625 1632 | + itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit |
1626 1633 | itemstack1.a("author", (NBTBase) (new NBTTagString(this.player.getName()))); |
1627 1634 | itemstack1.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title")))); |
1628 1635 | NBTTagList nbttaglist = itemstack.getTag().getList("pages", 8); |
1629 - | |
1636 + | |
1630 1637 | |
1631 1638 | itemstack1.a("pages", (NBTBase) nbttaglist); |
1632 1639 | itemstack1.setItem(Items.WRITTEN_BOOK); |
1633 1640 | + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit |
1634 1641 | } |
1635 1642 | } catch (Exception exception1) { |
1636 1643 | PlayerConnection.LOGGER.error("Couldn\'t sign book", exception1); |
1637 1644 | + this.disconnect("Invalid book data!"); // CraftBukkit |
1638 1645 | } |
1639 1646 | } else if ("MC|TrSel".equals(s)) { |
1640 1647 | try { |
1641 - | |
1648 + | |
1642 1649 | } |
1643 1650 | } catch (Exception exception2) { |
1644 1651 | PlayerConnection.LOGGER.error("Couldn\'t select trade", exception2); |
1645 1652 | + this.disconnect("Invalid trade data!"); // CraftBukkit |
1646 1653 | } |
1647 1654 | } else { |
1648 1655 | TileEntity tileentity; |
1649 - | |
1656 + | |
1650 1657 | } |
1651 1658 | } catch (Exception exception3) { |
1652 1659 | PlayerConnection.LOGGER.error("Couldn\'t set command block", exception3); |
1653 1660 | + this.disconnect("Invalid command data!"); // CraftBukkit |
1654 1661 | } |
1655 1662 | } else if ("MC|AutoCmd".equals(s)) { |
1656 1663 | if (!this.minecraftServer.getEnableCommandBlock()) { |
1657 - | |
1664 + | |
1658 1665 | } |
1659 1666 | } catch (Exception exception4) { |
1660 1667 | PlayerConnection.LOGGER.error("Couldn\'t set command block", exception4); |
1661 1668 | + this.disconnect("Invalid command data!"); // CraftBukkit |
1662 1669 | } |
1663 1670 | } else { |
1664 1671 | int k; |
1665 - | |
1672 + | |
1666 1673 | } |
1667 1674 | } catch (Exception exception5) { |
1668 1675 | PlayerConnection.LOGGER.error("Couldn\'t set beacon", exception5); |
1669 1676 | + this.disconnect("Invalid beacon data!"); // CraftBukkit |
1670 1677 | } |
1671 1678 | } |
1672 1679 | } else if ("MC|ItemName".equals(s)) { |
1673 - | |
1680 + | |
1674 1681 | } |
1675 1682 | } catch (Exception exception6) { |
1676 1683 | PlayerConnection.LOGGER.error("Couldn\'t set structure block", exception6); |
1677 1684 | + this.disconnect("Invalid structure data!"); // CraftBukkit |
1678 1685 | } |
1679 1686 | } else if ("MC|PickItem".equals(s)) { |
1680 1687 | packetdataserializer = packetplayincustompayload.b(); |
1681 - | |
1688 + | |
1682 1689 | this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); |
1683 1690 | } catch (Exception exception7) { |
1684 1691 | PlayerConnection.LOGGER.error("Couldn\'t pick item", exception7); |
1685 1692 | + this.disconnect("Invalid item data!"); // CraftBukkit |
1686 1693 | + } |
1687 1694 | + } |
1688 1695 | + // CraftBukkit start |
1689 1696 | + else if (packetplayincustompayload.a().equals("REGISTER")) { |
1690 1697 | + String channels = packetplayincustompayload.b().toString(com.google.common.base.Charsets.UTF_8); |
1691 1698 | + for (String channel : channels.split("\0")) { |