Commits
md_5 authored 9dafd1092f1
1 1 | --- a/net/minecraft/server/network/PlayerConnection.java |
2 2 | +++ b/net/minecraft/server/network/PlayerConnection.java |
3 - | |
3 + | |
4 4 | import org.apache.logging.log4j.LogManager; |
5 5 | import org.apache.logging.log4j.Logger; |
6 6 | |
7 7 | +// CraftBukkit start |
8 8 | +import java.util.concurrent.ExecutionException; |
9 9 | +import java.util.concurrent.atomic.AtomicInteger; |
10 10 | +import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; |
11 11 | +import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; |
12 12 | +import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving; |
13 13 | +import net.minecraft.network.protocol.game.PacketPlayOutSpawnPosition; |
51 51 | +import org.bukkit.event.player.PlayerResourcePackStatusEvent; |
52 52 | +import org.bukkit.event.player.PlayerSwapHandItemsEvent; |
53 53 | +import org.bukkit.event.player.PlayerTeleportEvent; |
54 54 | +import org.bukkit.event.player.PlayerToggleFlightEvent; |
55 55 | +import org.bukkit.event.player.PlayerToggleSneakEvent; |
56 56 | +import org.bukkit.event.player.PlayerToggleSprintEvent; |
57 57 | +import org.bukkit.inventory.CraftingInventory; |
58 58 | +import org.bukkit.inventory.EquipmentSlot; |
59 59 | +import org.bukkit.inventory.InventoryView; |
60 60 | +import org.bukkit.inventory.SmithingInventory; |
61 - | +import org.bukkit.util.NumberConversions; |
62 61 | +// CraftBukkit end |
63 62 | + |
64 63 | public class PlayerConnection implements ServerPlayerConnection, PacketListenerPlayIn { |
65 64 | |
66 65 | static final Logger LOGGER = LogManager.getLogger(); |
67 - | |
66 + | |
68 67 | private long keepAliveTime; |
69 68 | private boolean keepAlivePending; |
70 69 | private long keepAliveChallenge; |
71 70 | - private int chatSpamTickCount; |
72 71 | + // CraftBukkit start - multithreaded fields |
73 72 | + private final AtomicInteger chatSpamTickCount = new AtomicInteger(); |
74 73 | + // CraftBukkit end |
75 74 | private int dropSpamTickCount; |
76 75 | private double firstGoodX; |
77 76 | private double firstGoodY; |
78 - | |
77 + | |
79 78 | entityplayer.connection = this; |
80 79 | this.keepAliveTime = SystemUtils.getMillis(); |
81 80 | entityplayer.getTextFilter().join(); |
82 81 | + |
83 82 | + // CraftBukkit start - add fields and methods |
84 83 | + this.cserver = minecraftserver.server; |
85 84 | + } |
86 85 | + |
87 86 | + private final org.bukkit.craftbukkit.CraftServer cserver; |
88 87 | + public boolean processedDisconnect; |
89 88 | + private int lastTick = MinecraftServer.currentTick; |
90 89 | + private int allowedPlayerTicks = 1; |
91 90 | + private int lastDropTick = MinecraftServer.currentTick; |
92 91 | + private int lastBookTick = MinecraftServer.currentTick; |
93 92 | + private int dropCount = 0; |
94 - | + private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6; |
95 - | + private static final int CREATIVE_PLACE_DISTANCE_SQUARED = 7 * 7; |
96 93 | + |
97 94 | + // Get position of last block hit for BlockDamageLevel.STOPPED |
98 95 | + private double lastPosX = Double.MAX_VALUE; |
99 96 | + private double lastPosY = Double.MAX_VALUE; |
100 97 | + private double lastPosZ = Double.MAX_VALUE; |
101 98 | + private float lastPitch = Float.MAX_VALUE; |
102 99 | + private float lastYaw = Float.MAX_VALUE; |
103 100 | + private boolean justTeleported = false; |
104 101 | + |
105 102 | + public CraftPlayer getCraftPlayer() { |
106 103 | + return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); |
107 104 | } |
108 105 | + // CraftBukkit end |
109 106 | |
110 107 | public void tick() { |
111 108 | this.resetPosition(); |
112 - | |
109 + | |
113 110 | this.server.getProfiler().push("keepAlive"); |
114 111 | long i = SystemUtils.getMillis(); |
115 112 | |
116 113 | - if (i - this.keepAliveTime >= 15000L) { |
117 114 | + if (i - this.keepAliveTime >= 25000L) { // CraftBukkit |
118 115 | if (this.keepAlivePending) { |
119 116 | this.disconnect(new ChatMessage("disconnect.timeout")); |
120 117 | } else { |
121 - | |
118 + | |
122 119 | } |
123 120 | |
124 121 | this.server.getProfiler().pop(); |
125 122 | + // CraftBukkit start |
126 123 | + for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; |
127 124 | + /* Use thread-safe field access instead |
128 125 | if (this.chatSpamTickCount > 0) { |
129 126 | --this.chatSpamTickCount; |
130 127 | } |
131 128 | + */ |
132 129 | + // CraftBukkit end |
133 130 | |
134 131 | if (this.dropSpamTickCount > 0) { |
135 132 | --this.dropSpamTickCount; |
136 133 | } |
137 134 | |
138 135 | if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && SystemUtils.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { |
139 136 | + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 |
140 137 | this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); |
141 138 | } |
142 139 | |
143 - | |
140 + | |
144 141 | return this.server.isSingleplayerOwner(this.player.getGameProfile()); |
145 142 | } |
146 143 | |
147 144 | + // CraftBukkit start |
148 145 | + @Deprecated |
149 146 | public void disconnect(IChatBaseComponent ichatbasecomponent) { |
150 147 | + disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); |
151 148 | + } |
152 149 | + // CraftBukkit end |
153 150 | + |
181 178 | MinecraftServer minecraftserver = this.server; |
182 179 | NetworkManager networkmanager = this.connection; |
183 180 | |
184 181 | Objects.requireNonNull(this.connection); |
185 182 | - minecraftserver.executeBlocking(networkmanager::handleDisconnection); |
186 183 | + // CraftBukkit - Don't wait |
187 184 | + minecraftserver.wrapRunnable(networkmanager::handleDisconnection); |
188 185 | } |
189 186 | |
190 187 | private <T, R> void filterTextPacket(T t0, Consumer<R> consumer, BiFunction<ITextFilter, T, CompletableFuture<R>> bifunction) { |
191 - | |
188 + | |
192 189 | double d9 = entity.getDeltaMovement().lengthSqr(); |
193 190 | double d10 = d6 * d6 + d7 * d7 + d8 * d8; |
194 191 | |
195 192 | - if (d10 - d9 > 100.0D && !this.isSingleplayerOwner()) { |
196 193 | + |
197 194 | + // CraftBukkit start - handle custom speeds and skipped ticks |
198 195 | + this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; |
199 196 | + this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); |
200 197 | + this.lastTick = (int) (System.currentTimeMillis() / 50); |
201 198 | + |
217 214 | + } else { |
218 215 | + speed = player.getAbilities().walkingSpeed * 10f; |
219 216 | + } |
220 217 | + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player |
221 218 | + |
222 219 | + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { |
223 220 | + // CraftBukkit end |
224 221 | PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); |
225 222 | this.connection.send(new PacketPlayOutVehicleMove(entity)); |
226 223 | return; |
227 - | |
224 + | |
228 225 | } |
229 226 | |
230 227 | entity.absMoveTo(d3, d4, d5, f, f1); |
231 228 | + player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit |
232 229 | boolean flag2 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); |
233 230 | |
234 231 | if (flag && (flag1 || !flag2)) { |
235 232 | entity.absMoveTo(d0, d1, d2, f, f1); |
236 233 | + player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit |
237 234 | this.connection.send(new PacketPlayOutVehicleMove(entity)); |
290 287 | + this.justTeleported = false; |
291 288 | + return; |
292 289 | + } |
293 290 | + } |
294 291 | + } |
295 292 | + // CraftBukkit end |
296 293 | + |
297 294 | this.player.getLevel().getChunkSource().move(this.player); |
298 295 | this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d1, this.player.getZ() - d2); |
299 296 | this.clientVehicleIsFloating = d11 >= -0.03125D && !this.server.isFlightAllowed() && this.noBlocksAround(entity); |
300 - | |
297 + | |
301 298 | @Override |
302 299 | public void handleAcceptTeleportPacket(PacketPlayInTeleportAccept packetplayinteleportaccept) { |
303 300 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinteleportaccept, this, this.player.getLevel()); |
304 301 | - if (packetplayinteleportaccept.getId() == this.awaitingTeleport) { |
305 302 | + if (packetplayinteleportaccept.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit |
306 303 | this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); |
307 304 | this.lastGoodX = this.awaitingPositionFromClient.x; |
308 305 | this.lastGoodY = this.awaitingPositionFromClient.y; |
309 - | |
306 + | |
310 307 | } |
311 308 | |
312 309 | this.awaitingPositionFromClient = null; |
313 310 | + this.player.getLevel().getChunkSource().move(this.player); // CraftBukkit |
314 311 | } |
315 312 | |
316 313 | } |
317 - | |
314 + | |
318 315 | @Override |
319 316 | public void handleRecipeBookSeenRecipePacket(PacketPlayInRecipeDisplayed packetplayinrecipedisplayed) { |
320 317 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinrecipedisplayed, this, this.player.getLevel()); |
321 318 | - Optional optional = this.server.getRecipeManager().byKey(packetplayinrecipedisplayed.getRecipe()); |
322 319 | + Optional<? extends IRecipe<?>> optional = this.server.getRecipeManager().byKey(packetplayinrecipedisplayed.getRecipe()); // CraftBukkit - decompile error |
323 320 | RecipeBookServer recipebookserver = this.player.getRecipeBook(); |
324 321 | |
325 322 | Objects.requireNonNull(recipebookserver); |
326 - | |
323 + | |
327 324 | @Override |
328 325 | public void handleCustomCommandSuggestions(PacketPlayInTabComplete packetplayintabcomplete) { |
329 326 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayintabcomplete, this, this.player.getLevel()); |
330 327 | + // CraftBukkit start |
331 328 | + if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { |
332 329 | + this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); |
333 330 | + return; |
334 331 | + } |
335 332 | + // CraftBukkit end |
336 333 | StringReader stringreader = new StringReader(packetplayintabcomplete.getCommand()); |
337 334 | |
338 335 | if (stringreader.canRead() && stringreader.peek() == '/') { |
339 - | |
336 + | |
340 337 | ParseResults<CommandListenerWrapper> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); |
341 338 | |
342 339 | this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { |
343 340 | + if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer |
344 341 | this.connection.send(new PacketPlayOutTabComplete(packetplayintabcomplete.getId(), suggestions)); |
345 342 | }); |
346 343 | } |
347 - | |
344 + | |
348 345 | |
349 346 | if (container instanceof ContainerMerchant) { |
350 347 | ContainerMerchant containermerchant = (ContainerMerchant) container; |
351 348 | + // CraftBukkit start |
352 349 | + final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); |
353 350 | + if (tradeSelectEvent.isCancelled()) { |
354 351 | + this.player.getBukkitEntity().updateInventory(); |
355 352 | + return; |
356 353 | + } |
357 354 | + // CraftBukkit end |
358 355 | |
359 356 | containermerchant.setSelectionHint(i); |
360 357 | containermerchant.tryMoveItems(i); |
361 - | |
358 + | |
362 359 | |
363 360 | @Override |
364 361 | public void handleEditBook(PacketPlayInBEdit packetplayinbedit) { |
365 362 | + // CraftBukkit start |
366 363 | + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { |
367 364 | + this.disconnect("Book edited too quickly!"); |
368 365 | + return; |
369 366 | + } |
370 367 | + this.lastBookTick = MinecraftServer.currentTick; |
371 368 | + // CraftBukkit end |
372 369 | int i = packetplayinbedit.getSlot(); |
373 370 | |
374 371 | if (PlayerInventory.isHotbarSlot(i) || i == 40) { |
375 - | |
372 + | |
376 373 | |
377 374 | Objects.requireNonNull(list); |
378 375 | optional.ifPresent(list::add); |
379 376 | - Stream stream = packetplayinbedit.getPages().stream().limit(100L); |
380 377 | + Stream<String> stream = packetplayinbedit.getPages().stream().limit(100L); // CraftBukkit - decompile error |
381 378 | |
382 379 | Objects.requireNonNull(list); |
383 380 | stream.forEach(list::add); |
384 - | |
381 + | |
385 382 | ItemStack itemstack = this.player.getInventory().getItem(i); |
386 383 | |
387 384 | if (itemstack.is(Items.WRITABLE_BOOK)) { |
388 385 | - this.updateBookPages(list, UnaryOperator.identity(), itemstack); |
389 386 | + this.updateBookPages(list, UnaryOperator.identity(), itemstack.copy(), i, itemstack); // CraftBukkit |
390 387 | } |
391 388 | } |
392 389 | |
393 - | |
390 + | |
394 391 | |
395 392 | this.updateBookPages(list, (s) -> { |
396 393 | return IChatBaseComponent.ChatSerializer.toJson(new ChatComponentText(s)); |
397 394 | - }, itemstack1); |
398 395 | - this.player.getInventory().setItem(i, itemstack1); |
399 396 | + }, itemstack1, i, itemstack); // CraftBukkit |
400 397 | + this.player.getInventory().setItem(i, itemstack); // CraftBukkit - event factory updates the hand book |
401 398 | } |
402 399 | } |
403 400 | |
404 401 | - private void updateBookPages(List<ITextFilter.a> list, UnaryOperator<String> unaryoperator, ItemStack itemstack) { |
405 402 | + private void updateBookPages(List<ITextFilter.a> list, UnaryOperator<String> unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit |
406 403 | NBTTagList nbttaglist = new NBTTagList(); |
407 404 | |
408 405 | if (this.player.isTextFilteringEnabled()) { |
409 406 | - Stream stream = list.stream().map((itextfilter_a) -> { |
410 407 | + Stream<NBTTagString> stream = list.stream().map((itextfilter_a) -> { // CraftBukkit - decompile error |
411 408 | return NBTTagString.valueOf((String) unaryoperator.apply(itextfilter_a.getFiltered())); |
412 409 | }); |
413 410 | |
414 - | |
411 + | |
415 412 | } |
416 413 | |
417 414 | itemstack.addTagElement("pages", nbttaglist); |
418 415 | + CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit |
419 416 | } |
420 417 | |
421 418 | @Override |
422 - | |
419 + | |
423 420 | } else { |
424 421 | WorldServer worldserver = this.player.getLevel(); |
425 422 | |
426 423 | - if (!this.player.wonGame) { |
427 424 | + if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit |
428 425 | if (this.tickCount == 0) { |
429 426 | this.resetPosition(); |
430 427 | } |
431 - | |
428 + | |
432 429 | this.awaitingTeleportTime = this.tickCount; |
433 430 | this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); |
434 431 | } |
435 432 | - |
436 433 | + this.allowedPlayerTicks = 20; // CraftBukkit |
437 434 | } else { |
438 435 | this.awaitingTeleportTime = this.tickCount; |
439 436 | double d0 = clampHorizontal(packetplayinflying.getX(this.player.getX())); |
440 - | |
437 + | |
441 438 | if (this.player.isPassenger()) { |
442 439 | this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); |
443 440 | this.player.getLevel().getChunkSource().move(this.player); |
444 441 | + this.allowedPlayerTicks = 20; // CraftBukkit |
445 442 | } else { |
446 443 | + // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify |
447 444 | + double prevX = player.getX(); |
448 445 | + double prevY = player.getY(); |
449 446 | + double prevZ = player.getZ(); |
450 447 | + float prevYaw = player.getYRot(); |
451 448 | + float prevPitch = player.getXRot(); |
452 449 | + // CraftBukkit end |
453 450 | double d3 = this.player.getX(); |
454 451 | double d4 = this.player.getY(); |
455 452 | double d5 = this.player.getZ(); |
456 - | |
453 + | |
457 454 | ++this.receivedMovePacketCount; |
458 455 | int i = this.receivedMovePacketCount - this.knownMovePacketCount; |
459 456 | |
460 457 | - if (i > 5) { |
461 458 | + // CraftBukkit start - handle custom speeds and skipped ticks |
462 459 | + this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; |
463 460 | + this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); |
464 461 | + this.lastTick = (int) (System.currentTimeMillis() / 50); |
465 462 | + |
466 463 | + if (i > Math.max(this.allowedPlayerTicks, 5)) { |
482 479 | + |
483 480 | if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { |
484 481 | float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; |
485 482 | |
486 483 | - if (d11 - d10 > (double) (f2 * (float) i) && !this.isSingleplayerOwner()) { |
487 484 | + if (d11 - d10 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { |
488 485 | + // CraftBukkit end |
489 486 | PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d7, d8, d9); |
490 487 | this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); |
491 488 | return; |
492 - | |
489 + | |
493 490 | } |
494 491 | |
495 492 | this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); |
496 493 | + this.player.onGround = packetplayinflying.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move |
497 494 | double d12 = d8; |
498 495 | |
499 496 | d7 = d0 - this.player.getX(); |
500 - | |
497 + | |
501 498 | if (!this.player.noPhysics && !this.player.isSleeping() && (flag1 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) { |
502 499 | this.teleport(d3, d4, d5, f, f1); |
503 500 | } else { |
504 501 | - 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); |
505 502 | + // CraftBukkit start - fire PlayerMoveEvent |
506 503 | + // Rest to old location first |
507 504 | + this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); |
508 505 | + |
509 506 | + Player player = this.getCraftPlayer(); |
510 507 | + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. |
563 560 | + } |
564 561 | + } |
565 562 | + this.player.absMoveTo(d0, d1, d2, f, f1); // Copied from above |
566 563 | + |
567 564 | + // MC-135989, SPIGOT-5564: isRiptiding |
568 565 | + 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(); |
569 566 | + // CraftBukkit end |
570 567 | this.player.getLevel().getChunkSource().move(this.player); |
571 568 | this.player.doCheckFallDamage(this.player.getY() - d6, packetplayinflying.isOnGround()); |
572 569 | this.player.setOnGround(packetplayinflying.isOnGround()); |
573 - | |
570 + | |
574 571 | return true; |
575 572 | } |
576 573 | |
577 574 | + // CraftBukkit start - Delegate to teleport(Location) |
578 575 | public void dismount(double d0, double d1, double d2, float f, float f1) { |
579 576 | - this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), true); |
580 577 | + this.dismount(d0, d1, d2, f, f1, PlayerTeleportEvent.TeleportCause.UNKNOWN); |
581 578 | + } |
582 579 | + |
583 580 | + public void dismount(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { |
648 645 | + } |
649 646 | + if (Float.isNaN(f1)) { |
650 647 | + f1 = 0; |
651 648 | + } |
652 649 | + |
653 650 | + this.justTeleported = true; |
654 651 | + // CraftBukkit end |
655 652 | double d3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X) ? this.player.getX() : 0.0D; |
656 653 | double d4 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y) ? this.player.getY() : 0.0D; |
657 654 | double d5 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Z) ? this.player.getZ() : 0.0D; |
658 - | |
655 + | |
659 656 | this.awaitingTeleport = 0; |
660 657 | } |
661 658 | |
662 659 | + // CraftBukkit start - update last location |
663 660 | + this.lastPosX = this.awaitingPositionFromClient.x; |
664 661 | + this.lastPosY = this.awaitingPositionFromClient.y; |
665 662 | + this.lastPosZ = this.awaitingPositionFromClient.z; |
666 663 | + this.lastYaw = f; |
667 664 | + this.lastPitch = f1; |
668 665 | + // CraftBukkit end |
669 666 | + |
670 667 | this.awaitingTeleportTime = this.tickCount; |
671 668 | this.player.absMoveTo(d0, d1, d2, f, f1); |
672 669 | this.player.connection.send(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); |
673 - | |
670 + | |
674 671 | @Override |
675 672 | public void handlePlayerAction(PacketPlayInBlockDig packetplayinblockdig) { |
676 673 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockdig, this, this.player.getLevel()); |
677 674 | + if (this.player.isImmobile()) return; // CraftBukkit |
678 675 | BlockPosition blockposition = packetplayinblockdig.getPos(); |
679 676 | |
680 677 | this.player.resetLastActionTime(); |
681 - | |
678 + | |
682 679 | if (!this.player.isSpectator()) { |
683 680 | ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND); |
684 681 | |
685 682 | - this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); |
686 683 | - this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); |
687 684 | + // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) |
688 685 | + CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); |
689 686 | + CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); |
690 687 | + PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); |
691 688 | + this.cserver.getPluginManager().callEvent(swapItemsEvent); |
720 717 | + if (this.dropCount >= 20) { |
721 718 | + LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); |
722 719 | + this.disconnect("You dropped your items too quickly (Hacking?)"); |
723 720 | + return; |
724 721 | + } |
725 722 | + } |
726 723 | + // CraftBukkit end |
727 724 | this.player.drop(false); |
728 725 | } |
729 726 | |
730 - | |
727 + | |
731 728 | @Override |
732 729 | public void handleUseItemOn(PacketPlayInUseItem packetplayinuseitem) { |
733 730 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseitem, this, this.player.getLevel()); |
734 731 | + if (this.player.isImmobile()) return; // CraftBukkit |
735 732 | WorldServer worldserver = this.player.getLevel(); |
736 733 | EnumHand enumhand = packetplayinuseitem.getHand(); |
737 734 | ItemStack itemstack = this.player.getItemInHand(enumhand); |
738 - | |
735 + | |
736 + | |
737 + | this.player.resetLastActionTime(); |
738 + | int i = this.player.level.getMaxBuildHeight(); |
739 + | + // CraftBukkit start |
740 + | + double distanceSqr = this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); |
741 + | + if (distanceSqr > 100.0D) { |
742 + | + return; |
743 + | + } |
744 + | + // CraftBukkit end |
739 745 | |
740 746 | if (blockposition.getY() < i) { |
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)) { |
742 - | + // CraftBukkit start - Check if we can actually do something over this large a distance |
743 - | + Location eyeLoc = this.getCraftPlayer().getEyeLocation(); |
744 - | + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); |
745 - | + if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { |
746 - | + return; |
747 - | + } |
748 - | + this.player.stopUsingItem(); // SPIGOT-4706 |
749 - | + // CraftBukkit end |
747 + | - 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)) { |
748 + | + if (this.awaitingPositionFromClient == null && distanceSqr < 64.0D && worldserver.mayInteract(this.player, blockposition)) { // CraftBukkit - reuse value |
749 + | + this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 |
750 750 | EnumInteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); |
751 751 | |
752 752 | if (enumdirection == EnumDirection.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { |
753 - | |
753 + | |
754 754 | @Override |
755 755 | public void handleUseItem(PacketPlayInBlockPlace packetplayinblockplace) { |
756 756 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockplace, this, this.player.getLevel()); |
757 757 | + if (this.player.isImmobile()) return; // CraftBukkit |
758 758 | WorldServer worldserver = this.player.getLevel(); |
759 759 | EnumHand enumhand = packetplayinblockplace.getHand(); |
760 760 | ItemStack itemstack = this.player.getItemInHand(enumhand); |
761 761 | |
762 762 | this.player.resetLastActionTime(); |
763 763 | if (!itemstack.isEmpty()) { |
795 795 | + player.gameMode.firedInteract = false; |
796 796 | + } |
797 797 | + |
798 798 | + if (cancelled) { |
799 799 | + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 |
800 800 | + return; |
801 801 | + } |
802 802 | EnumInteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); |
803 803 | |
804 804 | if (enuminteractionresult.shouldSwing()) { |
805 - | |
805 + | |
806 806 | Entity entity = packetplayinspectate.getEntity(worldserver); |
807 807 | |
808 808 | if (entity != null) { |
809 809 | - this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); |
810 810 | + this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit |
811 811 | return; |
812 812 | } |
813 813 | } |
814 - | |
814 + | |
815 815 | PlayerConnection.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); |
816 816 | this.disconnect(new ChatMessage("multiplayer.requiredTexturePrompt.disconnect")); |
817 817 | } |
818 818 | + this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.action.ordinal()])); // CraftBukkit |
819 819 | |
820 820 | } |
821 821 | |
822 - | |
822 + | |
823 823 | |
824 824 | @Override |
825 825 | public void onDisconnect(IChatBaseComponent ichatbasecomponent) { |
826 826 | + // CraftBukkit start - Rarely it would send a disconnect line twice |
827 827 | + if (this.processedDisconnect) { |
828 828 | + return; |
829 829 | + } else { |
830 830 | + this.processedDisconnect = true; |
831 831 | + } |
832 832 | + // CraftBukkit end |
840 840 | this.player.disconnect(); |
841 841 | - this.server.getPlayerList().remove(this.player); |
842 842 | + String quitMessage = this.server.getPlayerList().remove(this.player); |
843 843 | + if ((quitMessage != null) && (quitMessage.length() > 0)) { |
844 844 | + this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); |
845 845 | + } |
846 846 | + // CraftBukkit end |
847 847 | this.player.getTextFilter().leave(); |
848 848 | if (this.isSingleplayerOwner()) { |
849 849 | PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out"); |
850 - | |
850 + | |
851 851 | } |
852 852 | |
853 853 | public void send(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) { |
854 854 | + // CraftBukkit start |
855 855 | + if (packet == null) { |
856 856 | + return; |
857 857 | + } else if (packet instanceof PacketPlayOutSpawnPosition) { |
858 858 | + PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet; |
859 859 | + this.player.compassTarget = new Location(this.getCraftPlayer().getWorld(), packet6.pos.getX(), packet6.pos.getY(), packet6.pos.getZ()); |
860 860 | + } |
861 861 | + // CraftBukkit end |
862 862 | + |
863 863 | try { |
864 864 | this.connection.send(packet, genericfuturelistener); |
865 865 | } catch (Throwable throwable) { |
866 - | |
866 + | |
867 867 | @Override |
868 868 | public void handleSetCarriedItem(PacketPlayInHeldItemSlot packetplayinhelditemslot) { |
869 869 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinhelditemslot, this, this.player.getLevel()); |
870 870 | + if (this.player.isImmobile()) return; // CraftBukkit |
871 871 | if (packetplayinhelditemslot.getSlot() >= 0 && packetplayinhelditemslot.getSlot() < PlayerInventory.getSelectionSize()) { |
872 872 | + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packetplayinhelditemslot.getSlot()); |
873 873 | + this.cserver.getPluginManager().callEvent(event); |
874 874 | + if (event.isCancelled()) { |
875 875 | + this.send(new PacketPlayOutHeldItemSlot(this.player.getInventory().selected)); |
876 876 | + this.player.resetLastActionTime(); |
877 877 | + return; |
878 878 | + } |
879 879 | + // CraftBukkit end |
880 880 | if (this.player.getInventory().selected != packetplayinhelditemslot.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { |
881 881 | this.player.stopUsingItem(); |
882 882 | } |
883 - | |
883 + | |
884 884 | this.player.resetLastActionTime(); |
885 885 | } else { |
886 886 | PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); |
887 887 | + this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit |
888 888 | } |
889 889 | } |
890 890 | |
891 891 | @Override |
892 892 | public void handleChat(PacketPlayInChat packetplayinchat) { |
893 893 | + // CraftBukkit start - async chat |
894 894 | + // SPIGOT-3638 |
895 895 | + if (this.server.isStopped()) { |
896 896 | + return; |
897 897 | + } |
898 898 | + // CraftBukkit end |
899 899 | String s = StringUtils.normalizeSpace(packetplayinchat.getMessage()); |
900 900 | |
901 901 | for (int i = 0; i < s.length(); ++i) { |
902 - | |
902 + | |
903 903 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinchat, this, this.player.getLevel()); |
904 904 | this.handleChat(ITextFilter.a.passThrough(s)); |
905 905 | } else { |
906 906 | - this.filterTextPacket(s, this::handleChat); |
907 907 | + this.handleChat(ITextFilter.a.passThrough(s)); // CraftBukkit - filter NYI |
908 908 | } |
909 909 | |
910 910 | } |
911 911 | |
912 912 | private void handleChat(ITextFilter.a itextfilter_a) { |
939 939 | + } |
940 940 | + }); |
941 941 | + } else if (this.player.getChatVisibility() == EnumChatVisibility.SYSTEM) { // Re-add "Command Only" flag check |
942 942 | + this.send(new PacketPlayOutChat((new ChatMessage("chat.cannotSend")).withStyle(EnumChatFormat.RED), ChatMessageType.SYSTEM, SystemUtils.NIL_UUID)); |
943 943 | + } else if (true) { |
944 944 | + this.chat(s, true); |
945 945 | + // CraftBukkit end - the below is for reference. :) |
946 946 | } else { |
947 947 | String s1 = itextfilter_a.getFiltered(); |
948 948 | ChatMessage chatmessage = s1.isEmpty() ? null : new ChatMessage("chat.type.text", new Object[]{this.player.getDisplayName(), s1}); |
949 - | |
949 + | |
950 950 | }, ChatMessageType.CHAT, this.player.getUUID()); |
951 951 | } |
952 952 | |
953 953 | - this.chatSpamTickCount += 20; |
954 954 | - if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { |
955 955 | - this.disconnect(new ChatMessage("disconnect.spam")); |
956 956 | + // CraftBukkit start - replaced with thread safe throttle |
957 957 | + // this.chatSpamTickCount += 20; |
958 958 | + if (chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { |
959 959 | + if (!isSync) { |
1142 1142 | + |
1143 1143 | + if (e2.isCancelled()) { |
1144 1144 | + return; |
1145 1145 | + } |
1146 1146 | + break; |
1147 1147 | + } |
1148 1148 | + // CraftBukkit end |
1149 1149 | this.player.resetLastActionTime(); |
1150 1150 | IJumpable ijumpable; |
1151 1151 | |
1152 - | |
1152 + | |
1153 1153 | @Override |
1154 1154 | public void handleInteract(PacketPlayInUseEntity packetplayinuseentity) { |
1155 1155 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseentity, this, this.player.getLevel()); |
1156 1156 | + if (this.player.isImmobile()) return; // CraftBukkit |
1157 1157 | WorldServer worldserver = this.player.getLevel(); |
1158 1158 | final Entity entity = packetplayinuseentity.getTarget(worldserver); |
1159 1159 | |
1160 - | |
1160 + | |
1161 1161 | |
1162 1162 | if (this.player.distanceToSqr(entity) < 36.0D) { |
1163 1163 | packetplayinuseentity.dispatch(new PacketPlayInUseEntity.c() { |
1164 1164 | - private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a) { |
1165 1165 | + private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit |
1166 1166 | ItemStack itemstack = PlayerConnection.this.player.getItemInHand(enumhand).copy(); |
1167 1167 | + // CraftBukkit start |
1168 1168 | + ItemStack itemInHand = PlayerConnection.this.player.getItemInHand(enumhand); |
1169 1169 | + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; |
1170 1170 | + Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); |
1196 1196 | |
1197 1197 | + // CraftBukkit start |
1198 1198 | + if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { |
1199 1199 | + player.containerMenu.sendAllDataToRemote(); |
1200 1200 | + } |
1201 1201 | + // CraftBukkit end |
1202 1202 | + |
1203 1203 | if (enuminteractionresult.consumesAction()) { |
1204 1204 | CriterionTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(PlayerConnection.this.player, itemstack, entity); |
1205 1205 | if (enuminteractionresult.shouldSwing()) { |
1206 - | |
1206 + | |
1207 1207 | |
1208 1208 | @Override |
1209 1209 | public void onInteraction(EnumHand enumhand) { |
1210 1210 | - this.performInteraction(enumhand, EntityHuman::interactOn); |
1211 1211 | + this.performInteraction(enumhand, EntityHuman::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (enumhand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); |
1212 1212 | } |
1213 1213 | |
1214 1214 | @Override |
1215 1215 | public void onInteraction(EnumHand enumhand, Vec3D vec3d) { |
1216 1216 | this.performInteraction(enumhand, (entityplayer, entity1, enumhand1) -> { |
1227 1227 | + ItemStack itemInHand = PlayerConnection.this.player.getMainHandItem(); |
1228 1228 | PlayerConnection.this.player.attack(entity); |
1229 1229 | + |
1230 1230 | + if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { |
1231 1231 | + player.containerMenu.sendAllDataToRemote(); |
1232 1232 | + } |
1233 1233 | + // CraftBukkit end |
1234 1234 | } else { |
1235 1235 | PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked")); |
1236 1236 | PlayerConnection.LOGGER.warn("Player {} tried to attack an invalid entity", PlayerConnection.this.player.getName().getString()); |
1237 - | |
1237 + | |
1238 1238 | @Override |
1239 1239 | public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow) { |
1240 1240 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel()); |
1241 1241 | + |
1242 1242 | + if (this.player.isImmobile()) return; // CraftBukkit |
1243 1243 | + CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit |
1244 1244 | + |
1245 1245 | this.player.doCloseContainer(); |
1246 1246 | } |
1247 1247 | |
1535 1535 | + if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { |
1536 1536 | + // Need to update the inventory on crafting to |
1537 1537 | + // correctly support custom recipes |
1538 1538 | + player.containerMenu.sendAllDataToRemote(); |
1539 1539 | + } |
1540 1540 | + } |
1541 1541 | + // CraftBukkit end |
1542 1542 | ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packetplayinwindowclick.getChangedSlots()).iterator(); |
1543 1543 | |
1544 1544 | while (objectiterator.hasNext()) { |
1545 - | |
1545 + | |
1546 1546 | @Override |
1547 1547 | public void handleContainerButtonClick(PacketPlayInEnchantItem packetplayinenchantitem) { |
1548 1548 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinenchantitem, this, this.player.getLevel()); |
1549 1549 | + if (this.player.isImmobile()) return; // CraftBukkit |
1550 1550 | this.player.resetLastActionTime(); |
1551 1551 | if (this.player.containerMenu.containerId == packetplayinenchantitem.getContainerId() && !this.player.isSpectator()) { |
1552 1552 | this.player.containerMenu.clickMenuButton(this.player, packetplayinenchantitem.getButtonId()); |
1553 - | |
1553 + | |
1554 1554 | |
1555 1555 | boolean flag1 = packetplayinsetcreativeslot.getSlotNum() >= 1 && packetplayinsetcreativeslot.getSlotNum() <= 45; |
1556 1556 | boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); |
1557 1557 | + if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem(), packetplayinsetcreativeslot.getItem()))) { // Insist on valid slot |
1558 1558 | + // CraftBukkit start - Call click event |
1559 1559 | + InventoryView inventory = this.player.inventoryMenu.getBukkitView(); |
1560 1560 | + org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.getItem()); |
1561 1561 | + |
1562 1562 | + SlotType type = SlotType.QUICKBAR; |
1563 1563 | + if (flag) { |
1587 1587 | + this.player.connection.send(new PacketPlayOutSetSlot(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinsetcreativeslot.getSlotNum(), this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem())); |
1588 1588 | + this.player.connection.send(new PacketPlayOutSetSlot(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); |
1589 1589 | + } |
1590 1590 | + return; |
1591 1591 | + } |
1592 1592 | + } |
1593 1593 | + // CraftBukkit end |
1594 1594 | |
1595 1595 | if (flag1 && flag2) { |
1596 1596 | this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).set(itemstack); |
1597 - | |
1597 + | |
1598 1598 | } |
1599 1599 | |
1600 1600 | private void updateSignText(PacketPlayInUpdateSign packetplayinupdatesign, List<ITextFilter.a> list) { |
1601 1601 | + if (this.player.isImmobile()) return; // CraftBukkit |
1602 1602 | this.player.resetLastActionTime(); |
1603 1603 | WorldServer worldserver = this.player.getLevel(); |
1604 1604 | BlockPosition blockposition = packetplayinupdatesign.getPos(); |
1605 - | |
1605 + | |
1606 1606 | |
1607 1607 | if (!tileentitysign.isEditable() || !this.player.getUUID().equals(tileentitysign.getPlayerWhoMayEdit())) { |
1608 1608 | PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString()); |
1609 1609 | + this.send(tileentity.getUpdatePacket()); // CraftBukkit |
1610 1610 | return; |
1611 1611 | } |
1612 1612 | |
1613 1613 | + // CraftBukkit start |
1614 1614 | + Player player = this.player.getBukkitEntity(); |
1615 1615 | + int x = packetplayinupdatesign.getPos().getX(); |
1635 1635 | + IChatBaseComponent[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); |
1636 1636 | + for (int i = 0; i < components.length; i++) { |
1637 1637 | + tileentitysign.setMessage(i, components[i]); |
1638 1638 | } |
1639 1639 | + tileentitysign.isEditable = false; |
1640 1640 | } |
1641 1641 | + // CraftBukkit end |
1642 1642 | |
1643 1643 | tileentitysign.setChanged(); |
1644 1644 | worldserver.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); |
1645 - | |
1645 + | |
1646 1646 | |
1647 1647 | @Override |
1648 1648 | public void handleKeepAlive(PacketPlayInKeepAlive packetplayinkeepalive) { |
1649 1649 | + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinkeepalive, this, this.player.getLevel()); // CraftBukkit |
1650 1650 | if (this.keepAlivePending && packetplayinkeepalive.getId() == this.keepAliveChallenge) { |
1651 1651 | int i = (int) (SystemUtils.getMillis() - this.keepAliveTime); |
1652 1652 | |
1653 - | |
1653 + | |
1654 1654 | @Override |
1655 1655 | public void handlePlayerAbilities(PacketPlayInAbilities packetplayinabilities) { |
1656 1656 | PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinabilities, this, this.player.getLevel()); |
1657 1657 | - this.player.getAbilities().flying = packetplayinabilities.isFlying() && this.player.getAbilities().mayfly; |
1658 1658 | + // CraftBukkit start |
1659 1659 | + if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packetplayinabilities.isFlying()) { |
1660 1660 | + PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packetplayinabilities.isFlying()); |
1661 1661 | + this.cserver.getPluginManager().callEvent(event); |
1662 1662 | + if (!event.isCancelled()) { |
1663 1663 | + this.player.getAbilities().flying = packetplayinabilities.isFlying(); // Actually set the player's flying status |
1664 1664 | + } else { |
1665 1665 | + this.player.onUpdateAbilities(); // Tell the player their ability was reverted |
1666 1666 | + } |
1667 1667 | + } |
1668 1668 | + // CraftBukkit end |
1669 1669 | } |
1670 1670 | |
1671 1671 | @Override |
1672 - | |
1672 + | |
1673 1673 | this.player.updateOptions(packetplayinsettings); |
1674 1674 | } |
1675 1675 | |
1676 1676 | - @Override |
1677 1677 | - public void handleCustomPayload(PacketPlayInCustomPayload packetplayincustompayload) {} |
1678 1678 | + // CraftBukkit start |
1679 1679 | + private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); |
1680 1680 | + private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); |
1681 1681 | + |
1682 1682 | + @Override |