From 88409ad861a7219b5f5a282aff300f37bf646d23 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 29 Jul 2018 05:02:15 +0100 Subject: [PATCH] Break up and make tab spam limits configurable Due to the changes in 1.13, clients will send a tab completion request for all bukkit commands in order to factor in the lack of support for brigadier and provide backwards support in the API. Craftbukkit, however; has moved the chat spam limiter to also interact with the tab completion request, which while good for avoiding abuse, causes 1.13 clients to easilly be kicked from a server in bukkit due to this. Removing the spam limit could cause issues for servers, however, there is no way for servers to manipulate this without blindly cancelling kick events, which only causes additional complications. This also causes issues in that the tab spam limit and chat share the same field but different limits, meaning that a player having typed a long command may be kicked from the server. Splitting the field up and making it configurable allows for server owners to take the burden of this into their own hand without having to rely on plugins doing unsafe things. --- .../ServerGamePacketListenerImpl.java.patch | 154 ++++++++++-------- 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index e440c0099..e814cf4e7 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -120,7 +120,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl implements ServerGamePacketListener, ServerPlayerConnection, TickablePacketListener { -@@ -247,7 +311,7 @@ +@@ -212,6 +276,7 @@ + private int tickCount; + private int ackBlockChangesUpTo = -1; + private final TickThrottler chatSpamThrottler = new TickThrottler(20, 200); ++ private final TickThrottler tabSpamThrottler = new TickThrottler(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement, io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit); // Paper - configurable tab spam limits + private final TickThrottler dropSpamThrottler = new TickThrottler(20, 1480); + private double firstGoodX; + private double firstGoodY; +@@ -247,7 +312,7 @@ private boolean waitingForSwitchToConfig; public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player, CommonListenerCookie clientData) { @@ -129,7 +137,7 @@ this.chunkSender = new PlayerChunkSender(connection.isMemoryConnection()); this.player = player; player.connection = this; -@@ -256,9 +320,25 @@ +@@ -256,9 +321,25 @@ Objects.requireNonNull(server); this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(uuid, server::enforceSecureProfile); @@ -156,7 +164,7 @@ @Override public void tick() { if (this.ackBlockChangesUpTo > -1) { -@@ -277,7 +357,7 @@ +@@ -277,7 +358,7 @@ if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) { if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player)) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); @@ -165,7 +173,7 @@ return; } } else { -@@ -296,7 +376,7 @@ +@@ -296,7 +377,7 @@ if (this.clientVehicleIsFloating && this.lastVehicle.getControllingPassenger() == this.player) { if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle)) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); @@ -174,15 +182,18 @@ return; } } else { -@@ -313,6 +393,7 @@ +@@ -311,8 +392,10 @@ + + this.keepConnectionAlive(); this.chatSpamThrottler.tick(); ++ this.tabSpamThrottler.tick(); // Paper - configurable tab spam limits this.dropSpamThrottler.tick(); if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 this.disconnect((Component) Component.translatable("multiplayer.disconnect.idling")); } -@@ -376,6 +457,12 @@ +@@ -376,6 +459,12 @@ @Override public void handlePlayerInput(ServerboundPlayerInputPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -195,7 +206,7 @@ this.player.setLastClientInput(packet.input()); } -@@ -401,6 +488,13 @@ +@@ -401,6 +490,13 @@ if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { ServerLevel worldserver = this.player.serverLevel(); @@ -209,7 +220,7 @@ double d0 = entity.getX(); double d1 = entity.getY(); double d2 = entity.getZ(); -@@ -415,7 +509,33 @@ +@@ -415,7 +511,33 @@ double d9 = entity.getDeltaMovement().lengthSqr(); double d10 = d6 * d6 + d7 * d7 + d8 * d8; @@ -244,7 +255,7 @@ ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); this.send(ClientboundMoveVehiclePacket.fromEntity(entity)); return; -@@ -449,19 +569,72 @@ +@@ -449,20 +571,73 @@ d10 = d6 * d6 + d7 * d7 + d8 * d8; boolean flag2 = false; @@ -263,8 +274,8 @@ + this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit this.send(ClientboundMoveVehiclePacket.fromEntity(entity)); return; -+ } -+ + } + + // CraftBukkit start - fire PlayerMoveEvent + Player player = this.getCraftPlayer(); + if (!this.hasMoved) { @@ -313,12 +324,13 @@ + this.justTeleported = false; + return; + } - } ++ } + // CraftBukkit end - ++ this.player.serverLevel().getChunkSource().move(this.player); entity.recordMovementThroughBlocks(new Vec3(d0, d1, d2), entity.position()); -@@ -499,6 +672,7 @@ + Vec3 vec3d = new Vec3(entity.getX() - d0, entity.getY() - d1, entity.getZ() - d2); +@@ -499,6 +674,7 @@ this.lastGoodZ = this.awaitingPositionFromClient.z; this.player.hasChangedDimension(); this.awaitingPositionFromClient = null; @@ -326,7 +338,7 @@ } } -@@ -528,6 +702,7 @@ +@@ -528,6 +704,7 @@ @Override public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -334,7 +346,7 @@ this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); } -@@ -545,18 +720,62 @@ +@@ -545,18 +722,62 @@ } @@ -347,7 +359,7 @@ - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async + // CraftBukkit start -+ if (!this.chatSpamThrottler.isIncrementAndUnderThreshold(1, 500) && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { ++ if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits + this.disconnect(Component.translatable("disconnect.spam")); + return; + } @@ -361,8 +373,8 @@ if (stringreader.canRead() && stringreader.peek() == '/') { stringreader.skip(); -+ } -+ + } + + final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), packet.getCommand(), true, null); + event.callEvent(); + final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); @@ -386,9 +398,9 @@ + } + } + this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); - } ++ } + } - ++ + private void sendServerSuggestions(final ServerboundCommandSuggestionPacket packet, final StringReader stringreader) { + // Paper end - AsyncTabCompleteEvent ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); @@ -398,7 +410,7 @@ Suggestions suggestions1 = suggestions.getList().size() <= 1000 ? suggestions : new Suggestions(suggestions.getRange(), suggestions.getList().subList(0, 1000)); this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions1)); -@@ -668,7 +887,7 @@ +@@ -668,7 +889,7 @@ ItemStack itemstack = iblockdata.getCloneItemStack(worldserver, blockposition, flag); if (!itemstack.isEmpty()) { @@ -407,7 +419,7 @@ ServerGamePacketListenerImpl.addBlockDataToItem(iblockdata, worldserver, blockposition, itemstack); } -@@ -866,6 +1085,13 @@ +@@ -866,6 +1087,13 @@ AbstractContainerMenu container = this.player.containerMenu; if (container instanceof MerchantMenu containermerchant) { @@ -421,7 +433,7 @@ if (!containermerchant.stillValid(this.player)) { ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containermerchant); return; -@@ -879,6 +1105,13 @@ +@@ -879,6 +1107,13 @@ @Override public void handleEditBook(ServerboundEditBookPacket packet) { @@ -435,7 +447,7 @@ int i = packet.slot(); if (Inventory.isHotbarSlot(i) || i == 40) { -@@ -899,12 +1132,16 @@ +@@ -899,12 +1134,16 @@ } private void updateBookContents(List pages, int slotId) { @@ -453,7 +465,7 @@ } } -@@ -915,12 +1152,13 @@ +@@ -915,12 +1154,13 @@ ItemStack itemstack1 = itemstack.transmuteCopy(Items.WRITTEN_BOOK); itemstack1.remove(DataComponents.WRITABLE_BOOK_CONTENT); @@ -469,7 +481,7 @@ } } -@@ -982,7 +1220,7 @@ +@@ -982,7 +1222,7 @@ } else { ServerLevel worldserver = this.player.serverLevel(); @@ -478,7 +490,7 @@ if (this.tickCount == 0) { this.resetPosition(); } -@@ -997,7 +1235,15 @@ +@@ -997,7 +1237,15 @@ if (this.player.isPassenger()) { this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); this.player.serverLevel().getChunkSource().move(this.player); @@ -494,7 +506,7 @@ double d3 = this.player.getX(); double d4 = this.player.getY(); double d5 = this.player.getZ(); -@@ -1019,15 +1265,33 @@ +@@ -1019,15 +1267,33 @@ ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; @@ -530,7 +542,7 @@ ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); return; -@@ -1043,12 +1307,40 @@ +@@ -1043,12 +1309,40 @@ boolean flag1 = d7 > 0.0D; if (this.player.onGround() && !packet.isOnGround() && flag1) { @@ -572,7 +584,7 @@ double d11 = d7; d6 = d0 - this.player.getX(); -@@ -1061,15 +1353,81 @@ +@@ -1061,15 +1355,81 @@ d10 = d6 * d6 + d7 * d7 + d8 * d8; boolean flag3 = false; @@ -656,7 +668,7 @@ this.player.absMoveTo(d0, d1, d2, f, f1); boolean flag4 = this.player.isAutoSpinAttack(); -@@ -1119,6 +1477,7 @@ +@@ -1119,6 +1479,7 @@ this.awaitingTeleportTime = this.tickCount; this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); } @@ -664,7 +676,7 @@ return true; } else { -@@ -1147,23 +1506,83 @@ +@@ -1147,23 +1508,83 @@ } public void teleport(double x, double y, double z, float yaw, float pitch) { @@ -751,7 +763,7 @@ if (this.player.hasClientLoaded()) { BlockPos blockposition = packet.getPos(); -@@ -1175,14 +1594,46 @@ +@@ -1175,14 +1596,46 @@ if (!this.player.isSpectator()) { ItemStack itemstack = this.player.getItemInHand(InteractionHand.OFF_HAND); @@ -800,7 +812,7 @@ this.player.drop(false); } -@@ -1216,11 +1667,33 @@ +@@ -1216,11 +1669,33 @@ return (item instanceof BlockItem || item instanceof BucketItem) && !player.getCooldowns().isOnCooldown(stack); } @@ -834,7 +846,7 @@ if (this.player.hasClientLoaded()) { this.player.connection.ackBlockChangesUpTo(packet.getSequence()); ServerLevel worldserver = this.player.serverLevel(); -@@ -1244,6 +1717,7 @@ +@@ -1244,6 +1719,7 @@ if (blockposition.getY() <= i) { if (this.awaitingPositionFromClient == null && worldserver.mayInteract(this.player, blockposition)) { @@ -842,7 +854,7 @@ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); if (enuminteractionresult.consumesAction()) { -@@ -1281,6 +1755,8 @@ +@@ -1281,6 +1757,8 @@ @Override public void handleUseItem(ServerboundUseItemPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -851,7 +863,7 @@ if (this.player.hasClientLoaded()) { this.ackBlockChangesUpTo(packet.getSequence()); ServerLevel worldserver = this.player.serverLevel(); -@@ -1296,6 +1772,47 @@ +@@ -1296,6 +1774,47 @@ this.player.absRotateTo(f, f1); } @@ -899,7 +911,7 @@ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); if (enuminteractionresult instanceof InteractionResult.Success) { -@@ -1321,7 +1838,7 @@ +@@ -1321,7 +1840,7 @@ Entity entity = packet.getEntity(worldserver); if (entity != null) { @@ -908,7 +920,7 @@ return; } } -@@ -1342,6 +1859,13 @@ +@@ -1342,6 +1861,13 @@ @Override public void onDisconnect(DisconnectionDetails info) { @@ -922,7 +934,7 @@ ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), info.reason().getString()); this.removePlayerFromWorld(); super.onDisconnect(info); -@@ -1349,10 +1873,20 @@ +@@ -1349,10 +1875,20 @@ private void removePlayerFromWorld() { this.chatMessageChain.close(); @@ -945,7 +957,7 @@ this.player.getTextFilter().leave(); } -@@ -1367,7 +1901,16 @@ +@@ -1367,7 +1903,16 @@ @Override public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -962,7 +974,7 @@ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { this.player.stopUsingItem(); } -@@ -1376,11 +1919,18 @@ +@@ -1376,11 +1921,18 @@ this.player.resetLastActionTime(); } else { ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); @@ -981,7 +993,7 @@ Optional optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages()); if (!optional.isEmpty()) { -@@ -1394,27 +1944,44 @@ +@@ -1394,27 +1946,44 @@ return; } @@ -1033,7 +1045,7 @@ ParseResults parseresults = this.parseCommand(command); if (this.server.enforceSecureProfile() && SignableCommand.hasSignableArguments(parseresults)) { -@@ -1431,19 +1998,37 @@ +@@ -1431,19 +2000,37 @@ if (!optional.isEmpty()) { this.tryHandleChat(packet.command(), () -> { @@ -1075,7 +1087,7 @@ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { this.handleMessageDecodeFailure(signedmessagechain_a); return; -@@ -1451,10 +2036,10 @@ +@@ -1451,10 +2038,10 @@ CommandSigningContext.SignedArguments commandsigningcontext_a = new CommandSigningContext.SignedArguments(map); @@ -1088,7 +1100,7 @@ } private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { -@@ -1530,14 +2115,20 @@ +@@ -1530,14 +2117,20 @@ return com_mojang_brigadier_commanddispatcher.parse(command, this.player.createCommandSourceStack()); } @@ -1113,7 +1125,7 @@ } } -@@ -1566,6 +2157,127 @@ +@@ -1566,6 +2159,127 @@ return false; } @@ -1241,7 +1253,7 @@ private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { SignedMessageBody signedmessagebody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); -@@ -1573,13 +2285,42 @@ +@@ -1573,13 +2287,42 @@ } private void broadcastChatMessage(PlayerChatMessage message) { @@ -1289,7 +1301,7 @@ this.disconnect((Component) Component.translatable("disconnect.spam")); } -@@ -1601,7 +2342,33 @@ +@@ -1601,7 +2344,33 @@ @Override public void handleAnimate(ServerboundSwingPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1323,7 +1335,7 @@ this.player.swing(packet.getHand()); } -@@ -1609,6 +2376,29 @@ +@@ -1609,6 +2378,29 @@ public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (this.player.hasClientLoaded()) { @@ -1353,7 +1365,7 @@ this.player.resetLastActionTime(); Entity entity; PlayerRideableJumping ijumpable; -@@ -1616,6 +2406,11 @@ +@@ -1616,6 +2408,11 @@ switch (packet.getAction()) { case PRESS_SHIFT_KEY: this.player.setShiftKeyDown(true); @@ -1365,7 +1377,7 @@ break; case RELEASE_SHIFT_KEY: this.player.setShiftKeyDown(false); -@@ -1691,6 +2486,12 @@ +@@ -1691,6 +2488,12 @@ } public void sendPlayerChatMessage(PlayerChatMessage message, ChatType.Bound params) { @@ -1378,7 +1390,7 @@ this.send(new ClientboundPlayerChatPacket(message.link().sender(), message.link().index(), message.signature(), message.signedBody().pack(this.messageSignatureCache), message.unsignedContent(), message.filterMask(), params)); this.addPendingMessage(message); } -@@ -1703,6 +2504,13 @@ +@@ -1703,6 +2506,13 @@ return this.connection.getRemoteAddress(); } @@ -1392,7 +1404,7 @@ public void switchToConfig() { this.waitingForSwitchToConfig = true; this.removePlayerFromWorld(); -@@ -1718,9 +2526,17 @@ +@@ -1718,9 +2528,17 @@ @Override public void handleInteract(ServerboundInteractPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1410,7 +1422,7 @@ this.player.resetLastActionTime(); this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); -@@ -1733,20 +2549,58 @@ +@@ -1733,20 +2551,58 @@ if (this.player.canInteractWithEntity(axisalignedbb, 3.0D)) { packet.dispatch(new ServerboundInteractPacket.Handler() { @@ -1473,7 +1485,7 @@ } } -@@ -1755,19 +2609,20 @@ +@@ -1755,19 +2611,20 @@ @Override public void onInteraction(InteractionHand hand) { @@ -1497,7 +1509,7 @@ label23: { if (entity instanceof AbstractArrow) { -@@ -1785,6 +2640,11 @@ +@@ -1785,6 +2642,11 @@ } ServerGamePacketListenerImpl.this.player.attack(entity); @@ -1509,7 +1521,7 @@ return; } } -@@ -1795,7 +2655,26 @@ +@@ -1795,7 +2657,26 @@ }); } } @@ -1536,7 +1548,7 @@ } } -@@ -1809,7 +2688,7 @@ +@@ -1809,7 +2690,7 @@ case PERFORM_RESPAWN: if (this.player.wonGame) { this.player.wonGame = false; @@ -1545,7 +1557,7 @@ this.resetPosition(); CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); } else { -@@ -1817,11 +2696,11 @@ +@@ -1817,11 +2698,11 @@ return; } @@ -1559,7 +1571,7 @@ } } break; -@@ -1833,16 +2712,27 @@ +@@ -1833,16 +2714,27 @@ @Override public void handleContainerClose(ServerboundContainerClosePacket packet) { @@ -1589,7 +1601,7 @@ this.player.containerMenu.sendAllDataToRemote(); } else if (!this.player.containerMenu.stillValid(this.player)) { ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); -@@ -1855,7 +2745,284 @@ +@@ -1855,7 +2747,284 @@ boolean flag = packet.getStateId() != this.player.containerMenu.getStateId(); this.player.containerMenu.suppressRemoteUpdates(); @@ -1875,7 +1887,7 @@ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); while (objectiterator.hasNext()) { -@@ -1901,8 +3068,22 @@ +@@ -1901,8 +3070,22 @@ return; } @@ -1899,7 +1911,7 @@ if (containerrecipebook_a == RecipeBookMenu.PostPlaceAction.PLACE_GHOST_RECIPE) { this.player.connection.send(new ClientboundPlaceGhostRecipePacket(this.player.containerMenu.containerId, craftingmanager_d.display().display())); } -@@ -1917,6 +3098,7 @@ +@@ -1917,6 +3100,7 @@ @Override public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1907,7 +1919,7 @@ this.player.resetLastActionTime(); if (this.player.containerMenu.containerId == packet.containerId() && !this.player.isSpectator()) { if (!this.player.containerMenu.stillValid(this.player)) { -@@ -1945,7 +3127,44 @@ +@@ -1945,7 +3129,44 @@ boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45; boolean flag2 = itemstack.isEmpty() || itemstack.getCount() <= itemstack.getMaxStackSize(); @@ -1952,7 +1964,7 @@ if (flag1 && flag2) { this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemstack); this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemstack); -@@ -1972,6 +3191,7 @@ +@@ -1972,6 +3193,7 @@ } private void updateSignText(ServerboundSignUpdatePacket packet, List signText) { @@ -1960,7 +1972,7 @@ this.player.resetLastActionTime(); ServerLevel worldserver = this.player.serverLevel(); BlockPos blockposition = packet.getPos(); -@@ -1993,7 +3213,17 @@ +@@ -1993,7 +3215,17 @@ @Override public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1979,7 +1991,7 @@ } @Override -@@ -2002,6 +3232,7 @@ +@@ -2002,6 +3234,7 @@ boolean flag = this.player.isModelPartShown(PlayerModelPart.HAT); this.player.updateOptions(packet.information()); @@ -1987,7 +1999,7 @@ if (this.player.isModelPartShown(PlayerModelPart.HAT) != flag) { this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT, this.player)); } -@@ -2058,7 +3289,7 @@ +@@ -2058,7 +3291,7 @@ if (!this.waitingForSwitchToConfig) { throw new IllegalStateException("Client acknowledged config, but none was requested"); } else { @@ -1996,7 +2008,7 @@ } } -@@ -2083,8 +3314,10 @@ +@@ -2083,8 +3316,10 @@ }); }