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.
This commit is contained in:
Shane Freeder 2018-07-29 05:02:15 +01:00
parent 30f16143ba
commit 88409ad861

View file

@ -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<com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion> 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<CommandSourceStack> 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<FilteredText> 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<LastSeenMessages> optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages());
if (!optional.isEmpty()) {
@@ -1394,27 +1944,44 @@
@@ -1394,27 +1946,44 @@
return;
}
@ -1033,7 +1045,7 @@
ParseResults<CommandSourceStack> 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<FilteredText> 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 @@
});
}