diff --git a/paper-server/patches/sources/com/mojang/brigadier/CommandDispatcher.java.patch b/paper-server/patches/sources/com/mojang/brigadier/CommandDispatcher.java.patch index 43c5d97060..dbb16b6bcb 100644 --- a/paper-server/patches/sources/com/mojang/brigadier/CommandDispatcher.java.patch +++ b/paper-server/patches/sources/com/mojang/brigadier/CommandDispatcher.java.patch @@ -8,7 +8,31 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; -@@ -537,10 +538,14 @@ +@@ -303,9 +304,15 @@ + } + final CommandContextBuilder context = contextSoFar.copy(); + final StringReader reader = new StringReader(originalReader); ++ boolean stop = false; // Paper - Handle non-recoverable exceptions + try { + try { + child.parse(reader, context); ++ // Paper start - Handle non-recoverable exceptions ++ } catch (final io.papermc.paper.brigadier.TagParseCommandSyntaxException e) { ++ stop = true; ++ throw e; ++ // Paper end - Handle non-recoverable exceptions + } catch (final RuntimeException ex) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().createWithContext(reader, ex.getMessage()); + } +@@ -320,6 +327,7 @@ + } + errors.put(child, ex); + reader.setCursor(cursor); ++ if (stop) return new ParseResults<>(contextSoFar, originalReader, errors); // Paper - Handle non-recoverable exceptions + continue; + } + +@@ -537,10 +545,14 @@ int i = 0; for (final CommandNode node : parent.getChildren()) { CompletableFuture future = Suggestions.empty(); diff --git a/paper-server/patches/sources/net/minecraft/commands/arguments/selector/SelectorPattern.java.patch b/paper-server/patches/sources/net/minecraft/commands/arguments/selector/SelectorPattern.java.patch new file mode 100644 index 0000000000..ed6f4da14b --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/commands/arguments/selector/SelectorPattern.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/commands/arguments/selector/SelectorPattern.java ++++ b/net/minecraft/commands/arguments/selector/SelectorPattern.java +@@ -13,7 +13,7 @@ + EntitySelectorParser entitySelectorParser = new EntitySelectorParser(new StringReader(selector), true); + return DataResult.success(new SelectorPattern(selector, entitySelectorParser.parse())); + } catch (CommandSyntaxException var2) { +- return DataResult.error(() -> "Invalid selector component: " + selector + ": " + var2.getMessage()); ++ return DataResult.error(() -> "Invalid selector component"); // Paper - limit selector error message + } + } + diff --git a/paper-server/patches/sources/net/minecraft/nbt/TagParser.java.patch b/paper-server/patches/sources/net/minecraft/nbt/TagParser.java.patch index b661474d3c..dd6b67ed47 100644 --- a/paper-server/patches/sources/net/minecraft/nbt/TagParser.java.patch +++ b/paper-server/patches/sources/net/minecraft/nbt/TagParser.java.patch @@ -1,6 +1,46 @@ --- a/net/minecraft/nbt/TagParser.java +++ b/net/minecraft/nbt/TagParser.java -@@ -253,11 +253,11 @@ +@@ -49,6 +49,7 @@ + }, CompoundTag::toString); + public static final Codec LENIENT_CODEC = Codec.withAlternative(AS_CODEC, CompoundTag.CODEC); + private final StringReader reader; ++ private int depth; // Paper + + public static CompoundTag parseTag(String string) throws CommandSyntaxException { + return new TagParser(new StringReader(string)).readSingleStruct(); +@@ -159,6 +160,7 @@ + + public CompoundTag readStruct() throws CommandSyntaxException { + this.expect('{'); ++ this.increaseDepth(); // Paper + CompoundTag compoundTag = new CompoundTag(); + this.reader.skipWhitespace(); + +@@ -182,6 +184,7 @@ + } + + this.expect('}'); ++ this.depth--; // Paper + return compoundTag; + } + +@@ -191,6 +194,7 @@ + if (!this.reader.canRead()) { + throw ERROR_EXPECTED_VALUE.createWithContext(this.reader); + } else { ++ this.increaseDepth(); // Paper + ListTag listTag = new ListTag(); + TagType tagType = null; + +@@ -216,6 +220,7 @@ + } + + this.expect(']'); ++ this.depth--; // Paper + return listTag; + } + } +@@ -253,11 +258,11 @@ } if (typeReader == ByteTag.TYPE) { @@ -15,3 +55,15 @@ } if (!this.hasElementSeparator()) { +@@ -288,4 +293,11 @@ + this.reader.skipWhitespace(); + this.reader.expect(c); + } ++ ++ private void increaseDepth() throws CommandSyntaxException { ++ this.depth++; ++ if (this.depth > 512) { ++ throw new io.papermc.paper.brigadier.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512"); ++ } ++ } + } diff --git a/paper-server/patches/sources/net/minecraft/network/chat/ComponentUtils.java.patch b/paper-server/patches/sources/net/minecraft/network/chat/ComponentUtils.java.patch index f2b2243462..c7b1b54e5a 100644 --- a/paper-server/patches/sources/net/minecraft/network/chat/ComponentUtils.java.patch +++ b/paper-server/patches/sources/net/minecraft/network/chat/ComponentUtils.java.patch @@ -1,6 +1,34 @@ --- a/net/minecraft/network/chat/ComponentUtils.java +++ b/net/minecraft/network/chat/ComponentUtils.java -@@ -41,6 +41,11 @@ +@@ -33,14 +33,39 @@ + } + } + ++ @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate. + public static Optional updateForEntity(@Nullable CommandSourceStack source, Optional text, @Nullable Entity sender, int depth) throws CommandSyntaxException { + return text.isPresent() ? Optional.of(updateForEntity(source, text.get(), sender, depth)) : Optional.empty(); + } + ++ // Paper start - validate separator ++ public static Optional updateSeparatorForEntity(@Nullable CommandSourceStack source, Optional text, @Nullable Entity sender, int depth) throws CommandSyntaxException { ++ if (text.isEmpty() || !isValidSelector(text.get())) return Optional.empty(); ++ return Optional.of(updateForEntity(source, text.get(), sender, depth)); ++ } ++ public static boolean isValidSelector(final Component component) { ++ final ComponentContents contents = component.getContents(); ++ ++ if (contents instanceof net.minecraft.network.chat.contents.NbtContents || contents instanceof net.minecraft.network.chat.contents.SelectorContents) return false; ++ if (contents instanceof final net.minecraft.network.chat.contents.TranslatableContents translatableContents) { ++ for (final Object arg : translatableContents.getArgs()) { ++ if (arg instanceof final Component argumentAsComponent && !isValidSelector(argumentAsComponent)) return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end - validate separator ++ + public static MutableComponent updateForEntity(@Nullable CommandSourceStack source, Component text, @Nullable Entity sender, int depth) throws CommandSyntaxException { if (depth > 100) { return text.copy(); } else { diff --git a/paper-server/patches/sources/net/minecraft/network/chat/contents/NbtContents.java.patch b/paper-server/patches/sources/net/minecraft/network/chat/contents/NbtContents.java.patch new file mode 100644 index 0000000000..f30203349e --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/network/chat/contents/NbtContents.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/network/chat/contents/NbtContents.java ++++ b/net/minecraft/network/chat/contents/NbtContents.java +@@ -120,7 +120,7 @@ + }).map(Tag::getAsString); + if (this.interpreting) { + Component component = DataFixUtils.orElse( +- ComponentUtils.updateForEntity(source, this.separator, sender, depth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR ++ ComponentUtils.updateSeparatorForEntity(source, this.separator, sender, depth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR // Paper - validate separator + ); + return stream.flatMap(text -> { + try { +@@ -132,7 +132,7 @@ + } + }).reduce((accumulator, current) -> accumulator.append(component).append(current)).orElseGet(Component::empty); + } else { +- return ComponentUtils.updateForEntity(source, this.separator, sender, depth) ++ return ComponentUtils.updateSeparatorForEntity(source, this.separator, sender, depth) // Paper - validate separator + .map( + text -> stream.map(Component::literal) + .reduce((accumulator, current) -> accumulator.append(text).append(current)) diff --git a/paper-server/patches/sources/net/minecraft/network/chat/contents/SelectorContents.java.patch b/paper-server/patches/sources/net/minecraft/network/chat/contents/SelectorContents.java.patch new file mode 100644 index 0000000000..aff540bbdc --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/network/chat/contents/SelectorContents.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/network/chat/contents/SelectorContents.java ++++ b/net/minecraft/network/chat/contents/SelectorContents.java +@@ -36,7 +36,7 @@ + if (source == null) { + return Component.empty(); + } else { +- Optional optional = ComponentUtils.updateForEntity(source, this.separator, sender, depth); ++ Optional optional = ComponentUtils.updateSeparatorForEntity(source, this.separator, sender, depth); // Paper - validate separator + return ComponentUtils.formatList(this.selector.resolved().findEntities(source), optional, Entity::getDisplayName); + } + } diff --git a/paper-server/patches/sources/net/minecraft/network/chat/contents/TranslatableContents.java.patch b/paper-server/patches/sources/net/minecraft/network/chat/contents/TranslatableContents.java.patch new file mode 100644 index 0000000000..88b91fae6d --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/network/chat/contents/TranslatableContents.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/network/chat/contents/TranslatableContents.java ++++ b/net/minecraft/network/chat/contents/TranslatableContents.java +@@ -181,6 +181,15 @@ + + @Override + public Optional visit(FormattedText.ContentConsumer visitor) { ++ // Paper start - Count visited parts ++ try { ++ return this.visit(new TranslatableContentConsumer<>(visitor)); ++ } catch (IllegalArgumentException ignored) { ++ return visitor.accept("..."); ++ } ++ } ++ private Optional visit(TranslatableContentConsumer visitor) { ++ // Paper end - Count visited parts + this.decompose(); + + for (FormattedText formattedText : this.decomposedParts) { +@@ -191,7 +200,26 @@ + } + + return Optional.empty(); ++ } ++ // Paper start - Count visited parts ++ private static final class TranslatableContentConsumer implements FormattedText.ContentConsumer { ++ private static final IllegalArgumentException EX = new IllegalArgumentException("Too long"); ++ private final FormattedText.ContentConsumer visitor; ++ private int visited; ++ ++ private TranslatableContentConsumer(FormattedText.ContentConsumer visitor) { ++ this.visitor = visitor; ++ } ++ ++ @Override ++ public Optional accept(final String asString) { ++ if (visited++ > 32) { ++ throw EX; ++ } ++ return this.visitor.accept(asString); ++ } + } ++ // Paper end - Count visited parts + + @Override + public MutableComponent resolve(@Nullable CommandSourceStack source, @Nullable Entity sender, int depth) throws CommandSyntaxException { diff --git a/paper-server/patches/sources/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java.patch b/paper-server/patches/sources/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java.patch new file mode 100644 index 0000000000..1771a837ae --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java ++++ b/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +@@ -19,7 +19,7 @@ + + private ServerboundCommandSuggestionPacket(FriendlyByteBuf buf) { + this.id = buf.readVarInt(); +- this.command = buf.readUtf(32500); ++ this.command = buf.readUtf(2048); // Paper + } + + private void write(FriendlyByteBuf buf) { 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 060cd62424..160c552296 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 @@ -442,7 +442,7 @@ this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); } -@@ -545,21 +758,90 @@ +@@ -545,21 +758,104 @@ } @@ -465,6 +465,13 @@ + return; + } + // Paper end - Don't suggest if tab-complete is disabled ++ // Paper start ++ final int index; ++ if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) { ++ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); ++ return; ++ } ++ // Paper end + // Paper start - AsyncTabCompleteEvent + TAB_COMPLETE_EXECUTOR.execute(() -> this.handleCustomCommandSuggestions0(packet)); + } @@ -474,8 +481,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(); @@ -506,17 +513,24 @@ + this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), limitTo(suggestEvent.getSuggestions(), ServerGamePacketListenerImpl.MAX_COMMAND_SUGGESTIONS))); + } + // Paper end - Brigadier API - } ++ } + } + // Paper start - brig API + private static Suggestions limitTo(final Suggestions suggestions, final int size) { + return suggestions.getList().size() <= size ? suggestions : new Suggestions(suggestions.getRange(), suggestions.getList().subList(0, size)); + } + // Paper end - brig API - ++ + private void sendServerSuggestions(final ServerboundCommandSuggestionPacket packet, final StringReader stringreader) { + // Paper end - AsyncTabCompleteEvent ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ // Paper start - Handle non-recoverable exceptions ++ if (!parseresults.getExceptions().isEmpty() ++ && parseresults.getExceptions().values().stream().anyMatch(e -> e instanceof io.papermc.paper.brigadier.TagParseCommandSyntaxException)) { ++ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); ++ return; ++ } ++ // Paper end - Handle non-recoverable exceptions this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { - Suggestions suggestions1 = suggestions.getList().size() <= 1000 ? suggestions : new Suggestions(suggestions.getRange(), suggestions.getList().subList(0, 1000)); @@ -537,7 +551,7 @@ }); } -@@ -568,7 +850,7 @@ +@@ -568,7 +864,7 @@ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (!this.server.isCommandBlockEnabled()) { this.player.sendSystemMessage(Component.translatable("advMode.notEnabled")); @@ -546,7 +560,7 @@ this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); } else { BaseCommandBlock commandblocklistenerabstract = null; -@@ -635,7 +917,7 @@ +@@ -635,7 +931,7 @@ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (!this.server.isCommandBlockEnabled()) { this.player.sendSystemMessage(Component.translatable("advMode.notEnabled")); @@ -555,7 +569,7 @@ this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); } else { BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level()); -@@ -668,7 +950,7 @@ +@@ -668,7 +964,7 @@ ItemStack itemstack = iblockdata.getCloneItemStack(worldserver, blockposition, flag); if (!itemstack.isEmpty()) { @@ -564,7 +578,7 @@ ServerGamePacketListenerImpl.addBlockDataToItem(iblockdata, worldserver, blockposition, itemstack); } -@@ -712,15 +994,25 @@ +@@ -712,15 +1008,25 @@ if (stack.isItemEnabled(this.player.level().enabledFeatures())) { Inventory playerinventory = this.player.getInventory(); int i = playerinventory.findSlotMatchingItem(stack); @@ -594,7 +608,7 @@ } this.player.connection.send(new ClientboundSetHeldSlotPacket(playerinventory.selected)); -@@ -866,6 +1158,13 @@ +@@ -866,6 +1172,13 @@ AbstractContainerMenu container = this.player.containerMenu; if (container instanceof MerchantMenu containermerchant) { @@ -608,7 +622,7 @@ if (!containermerchant.stillValid(this.player)) { ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containermerchant); return; -@@ -879,6 +1178,51 @@ +@@ -879,6 +1192,51 @@ @Override public void handleEditBook(ServerboundEditBookPacket packet) { @@ -660,7 +674,7 @@ int i = packet.slot(); if (Inventory.isHotbarSlot(i) || i == 40) { -@@ -899,12 +1243,16 @@ +@@ -899,12 +1257,16 @@ } private void updateBookContents(List pages, int slotId) { @@ -678,7 +692,7 @@ } } -@@ -915,12 +1263,13 @@ +@@ -915,12 +1277,13 @@ ItemStack itemstack1 = itemstack.transmuteCopy(Items.WRITTEN_BOOK); itemstack1.remove(DataComponents.WRITABLE_BOOK_CONTENT); @@ -694,7 +708,7 @@ } } -@@ -978,26 +1327,34 @@ +@@ -978,26 +1341,34 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) { @@ -736,7 +750,7 @@ double d3 = this.player.getX(); double d4 = this.player.getY(); double d5 = this.player.getZ(); -@@ -1005,7 +1362,16 @@ +@@ -1005,7 +1376,16 @@ double d7 = d1 - this.firstGoodY; double d8 = d2 - this.firstGoodZ; double d9 = this.player.getDeltaMovement().lengthSqr(); @@ -754,7 +768,7 @@ if (this.player.isSleeping()) { if (d10 > 1.0D) { -@@ -1019,36 +1385,106 @@ +@@ -1019,36 +1399,106 @@ ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; @@ -870,7 +884,7 @@ double d11 = d7; d6 = d0 - this.player.getX(); -@@ -1059,17 +1495,100 @@ +@@ -1059,17 +1509,100 @@ d8 = d2 - this.player.getZ(); d10 = d6 * d6 + d7 * d7 + d8 * d8; @@ -976,7 +990,7 @@ this.player.absMoveTo(d0, d1, d2, f, f1); boolean flag4 = this.player.isAutoSpinAttack(); -@@ -1119,6 +1638,7 @@ +@@ -1119,6 +1652,7 @@ this.awaitingTeleportTime = this.tickCount; this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); } @@ -984,7 +998,7 @@ return true; } else { -@@ -1147,23 +1667,98 @@ +@@ -1147,23 +1681,98 @@ } public void teleport(double x, double y, double z, float yaw, float pitch) { @@ -1086,7 +1100,7 @@ if (this.player.hasClientLoaded()) { BlockPos blockposition = packet.getPos(); -@@ -1175,14 +1770,46 @@ +@@ -1175,14 +1784,46 @@ if (!this.player.isSpectator()) { ItemStack itemstack = this.player.getItemInHand(InteractionHand.OFF_HAND); @@ -1135,7 +1149,7 @@ this.player.drop(false); } -@@ -1199,8 +1826,34 @@ +@@ -1199,8 +1840,34 @@ case START_DESTROY_BLOCK: case ABORT_DESTROY_BLOCK: case STOP_DESTROY_BLOCK: @@ -1170,13 +1184,10 @@ return; default: throw new IllegalArgumentException("Invalid player action"); -@@ -1215,12 +1868,34 @@ - Item item = stack.getItem(); +@@ -1218,9 +1885,31 @@ + } + } - return (item instanceof BlockItem || item instanceof BucketItem) && !player.getCooldowns().isOnCooldown(stack); -+ } -+ } -+ + // Spigot start - limit place/interactions + private int limitedPackets; + private long lastLimitedPacket = -1; @@ -1191,12 +1202,12 @@ + this.lastLimitedPacket = timestamp; + this.limitedPackets = 0; + return true; - } ++ } + + return true; - } ++ } + // Spigot end - ++ @Override public void handleUseItemOn(ServerboundUseItemOnPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1205,7 +1216,7 @@ if (this.player.hasClientLoaded()) { this.player.connection.ackBlockChangesUpTo(packet.getSequence()); ServerLevel worldserver = this.player.serverLevel(); -@@ -1230,6 +1905,11 @@ +@@ -1230,6 +1919,11 @@ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { BlockHitResult movingobjectpositionblock = packet.getHitResult(); Vec3 vec3d = movingobjectpositionblock.getLocation(); @@ -1217,7 +1228,7 @@ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); if (this.player.canInteractWithBlock(blockposition, 1.0D)) { -@@ -1243,7 +1923,8 @@ +@@ -1243,7 +1937,8 @@ int i = this.player.level().getMaxY(); if (blockposition.getY() <= i) { @@ -1227,7 +1238,7 @@ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); if (enuminteractionresult.consumesAction()) { -@@ -1257,11 +1938,11 @@ +@@ -1257,11 +1952,11 @@ } else if (enuminteractionresult instanceof InteractionResult.Success) { InteractionResult.Success enuminteractionresult_d = (InteractionResult.Success) enuminteractionresult; @@ -1241,7 +1252,7 @@ } else { MutableComponent ichatmutablecomponent1 = Component.translatable("build.tooHigh", i).withStyle(ChatFormatting.RED); -@@ -1281,6 +1962,8 @@ +@@ -1281,6 +1976,8 @@ @Override public void handleUseItem(ServerboundUseItemPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1250,7 +1261,7 @@ if (this.player.hasClientLoaded()) { this.ackBlockChangesUpTo(packet.getSequence()); ServerLevel worldserver = this.player.serverLevel(); -@@ -1296,6 +1979,47 @@ +@@ -1296,6 +1993,47 @@ this.player.absRotateTo(f, f1); } @@ -1298,7 +1309,7 @@ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); if (enuminteractionresult instanceof InteractionResult.Success) { -@@ -1321,7 +2045,7 @@ +@@ -1321,7 +2059,7 @@ Entity entity = packet.getEntity(worldserver); if (entity != null) { @@ -1307,7 +1318,7 @@ return; } } -@@ -1342,22 +2066,52 @@ +@@ -1342,22 +2080,52 @@ @Override public void onDisconnect(DisconnectionDetails info) { @@ -1364,7 +1375,7 @@ throw new IllegalArgumentException("Expected packet sequence nr >= 0"); } else { this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo); -@@ -1367,7 +2121,17 @@ +@@ -1367,7 +2135,17 @@ @Override public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1382,7 +1393,7 @@ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { this.player.stopUsingItem(); } -@@ -1376,11 +2140,18 @@ +@@ -1376,11 +2154,18 @@ this.player.resetLastActionTime(); } else { ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); @@ -1401,7 +1412,7 @@ Optional optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages()); if (!optional.isEmpty()) { -@@ -1394,27 +2165,46 @@ +@@ -1394,27 +2179,46 @@ return; } @@ -1455,7 +1466,7 @@ ParseResults parseresults = this.parseCommand(command); if (this.server.enforceSecureProfile() && SignableCommand.hasSignableArguments(parseresults)) { -@@ -1431,19 +2221,39 @@ +@@ -1431,19 +2235,39 @@ if (!optional.isEmpty()) { this.tryHandleChat(packet.command(), () -> { @@ -1499,7 +1510,7 @@ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { this.handleMessageDecodeFailure(signedmessagechain_a); return; -@@ -1451,10 +2261,10 @@ +@@ -1451,10 +2275,10 @@ CommandSigningContext.SignedArguments commandsigningcontext_a = new CommandSigningContext.SignedArguments(map); @@ -1512,7 +1523,7 @@ } private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { -@@ -1530,14 +2340,20 @@ +@@ -1530,14 +2354,20 @@ return com_mojang_brigadier_commanddispatcher.parse(command, this.player.createCommandSourceStack()); } @@ -1538,7 +1549,7 @@ } } -@@ -1549,7 +2365,7 @@ +@@ -1549,7 +2379,7 @@ if (optional.isEmpty()) { ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); @@ -1547,7 +1558,7 @@ } return optional; -@@ -1564,8 +2380,129 @@ +@@ -1564,8 +2394,129 @@ } return false; @@ -1677,7 +1688,7 @@ private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { SignedMessageBody signedmessagebody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); -@@ -1573,15 +2510,44 @@ +@@ -1573,15 +2524,44 @@ } private void broadcastChatMessage(PlayerChatMessage message) { @@ -1728,7 +1739,7 @@ } -@@ -1592,7 +2558,7 @@ +@@ -1592,7 +2572,7 @@ synchronized (this.lastSeenMessages) { if (!this.lastSeenMessages.applyOffset(packet.offset())) { ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); @@ -1737,7 +1748,7 @@ } } -@@ -1601,7 +2567,40 @@ +@@ -1601,7 +2581,40 @@ @Override public void handleAnimate(ServerboundSwingPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1778,7 +1789,7 @@ this.player.swing(packet.getHand()); } -@@ -1609,6 +2608,29 @@ +@@ -1609,6 +2622,29 @@ public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (this.player.hasClientLoaded()) { @@ -1808,7 +1819,7 @@ this.player.resetLastActionTime(); Entity entity; PlayerRideableJumping ijumpable; -@@ -1616,6 +2638,11 @@ +@@ -1616,6 +2652,11 @@ switch (packet.getAction()) { case PRESS_SHIFT_KEY: this.player.setShiftKeyDown(true); @@ -1820,7 +1831,7 @@ break; case RELEASE_SHIFT_KEY: this.player.setShiftKeyDown(false); -@@ -1684,13 +2711,19 @@ +@@ -1684,13 +2725,19 @@ } if (i > 4096) { @@ -1841,7 +1852,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); } -@@ -1701,7 +2734,19 @@ +@@ -1701,7 +2748,19 @@ public SocketAddress getRemoteAddress() { return this.connection.getRemoteAddress(); @@ -1861,7 +1872,7 @@ public void switchToConfig() { this.waitingForSwitchToConfig = true; -@@ -1718,9 +2763,17 @@ +@@ -1718,9 +2777,17 @@ @Override public void handleInteract(ServerboundInteractPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1879,7 +1890,7 @@ this.player.resetLastActionTime(); this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); -@@ -1733,20 +2786,59 @@ +@@ -1733,20 +2800,59 @@ if (this.player.canInteractWithEntity(axisalignedbb, 3.0D)) { packet.dispatch(new ServerboundInteractPacket.Handler() { @@ -1943,7 +1954,7 @@ } } -@@ -1755,19 +2847,20 @@ +@@ -1755,19 +2861,20 @@ @Override public void onInteraction(InteractionHand hand) { @@ -1967,7 +1978,7 @@ label23: { if (entity instanceof AbstractArrow) { -@@ -1785,17 +2878,41 @@ +@@ -1785,17 +2892,41 @@ } ServerGamePacketListenerImpl.this.player.attack(entity); @@ -2010,7 +2021,7 @@ } } -@@ -1809,7 +2926,7 @@ +@@ -1809,7 +2940,7 @@ case PERFORM_RESPAWN: if (this.player.wonGame) { this.player.wonGame = false; @@ -2019,7 +2030,7 @@ this.resetPosition(); CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); } else { -@@ -1817,11 +2934,11 @@ +@@ -1817,11 +2948,11 @@ return; } @@ -2034,7 +2045,7 @@ } } break; -@@ -1833,16 +2950,27 @@ +@@ -1833,16 +2964,27 @@ @Override public void handleContainerClose(ServerboundContainerClosePacket packet) { @@ -2064,7 +2075,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 +2983,303 @@ +@@ -1855,7 +2997,303 @@ boolean flag = packet.getStateId() != this.player.containerMenu.getStateId(); this.player.containerMenu.suppressRemoteUpdates(); @@ -2369,7 +2380,7 @@ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); while (objectiterator.hasNext()) { -@@ -1879,6 +3303,14 @@ +@@ -1879,6 +3317,14 @@ @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { @@ -2384,7 +2395,7 @@ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); this.player.resetLastActionTime(); if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.containerId()) { -@@ -1900,8 +3332,42 @@ +@@ -1900,8 +3346,42 @@ ServerGamePacketListenerImpl.LOGGER.debug("Player {} tried to place impossible recipe {}", this.player, recipeholder.id().location()); return; } @@ -2428,7 +2439,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 +3383,7 @@ +@@ -1917,6 +3397,7 @@ @Override public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -2436,7 +2447,7 @@ this.player.resetLastActionTime(); if (this.player.containerMenu.containerId == packet.containerId() && !this.player.isSpectator()) { if (!this.player.containerMenu.stillValid(this.player)) { -@@ -1945,7 +3412,44 @@ +@@ -1945,7 +3426,44 @@ boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45; boolean flag2 = itemstack.isEmpty() || itemstack.getCount() <= itemstack.getMaxStackSize(); @@ -2481,7 +2492,7 @@ if (flag1 && flag2) { this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemstack); this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemstack); -@@ -1964,7 +3468,19 @@ +@@ -1964,7 +3482,19 @@ @Override public void handleSignUpdate(ServerboundSignUpdatePacket packet) { @@ -2502,7 +2513,7 @@ this.filterTextPacket(list).thenAcceptAsync((list1) -> { this.updateSignText(packet, list1); -@@ -1972,6 +3488,7 @@ +@@ -1972,6 +3502,7 @@ } private void updateSignText(ServerboundSignUpdatePacket packet, List signText) { @@ -2510,7 +2521,7 @@ this.player.resetLastActionTime(); ServerLevel worldserver = this.player.serverLevel(); BlockPos blockposition = packet.getPos(); -@@ -1993,15 +3510,33 @@ +@@ -1993,15 +3524,33 @@ @Override public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -2545,7 +2556,7 @@ if (this.player.isModelPartShown(PlayerModelPart.HAT) != flag) { this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT, this.player)); } -@@ -2012,7 +3547,7 @@ +@@ -2012,7 +3561,7 @@ public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (this.player.hasPermissions(2) || this.isSingleplayerOwner()) { @@ -2554,7 +2565,7 @@ } } -@@ -2033,7 +3568,7 @@ +@@ -2033,7 +3582,7 @@ if (!Objects.equals(profilepublickey_a, profilepublickey_a1)) { if (profilepublickey_a != null && profilepublickey_a1.expiresAt().isBefore(profilepublickey_a.expiresAt())) { @@ -2563,7 +2574,7 @@ } else { try { SignatureValidator signaturevalidator = this.server.getProfileKeySignatureValidator(); -@@ -2045,8 +3580,8 @@ +@@ -2045,8 +3594,8 @@ this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator)); } catch (ProfilePublicKey.ValidationException profilepublickey_b) { @@ -2574,7 +2585,7 @@ } } -@@ -2058,7 +3593,7 @@ +@@ -2058,7 +3607,7 @@ if (!this.waitingForSwitchToConfig) { throw new IllegalStateException("Client acknowledged config, but none was requested"); } else { @@ -2583,7 +2594,7 @@ } } -@@ -2076,15 +3611,18 @@ +@@ -2076,15 +3625,18 @@ private void resetPlayerChatState(RemoteChatSession session) { this.chatSession = session; @@ -2605,7 +2616,7 @@ @Override public void handleClientTickEnd(ServerboundClientTickEndPacket packet) { -@@ -2115,4 +3653,17 @@ +@@ -2115,4 +3667,17 @@ InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand); } diff --git a/paper-server/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java b/paper-server/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java new file mode 100644 index 0000000000..a375ad4ba9 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/brigadier/TagParseCommandSyntaxException.java @@ -0,0 +1,15 @@ +package io.papermc.paper.brigadier; + +import com.mojang.brigadier.LiteralMessage; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.minecraft.network.chat.Component; + +public final class TagParseCommandSyntaxException extends CommandSyntaxException { + + private static final SimpleCommandExceptionType EXCEPTION_TYPE = new SimpleCommandExceptionType(new LiteralMessage("Error parsing NBT")); + + public TagParseCommandSyntaxException(final String message) { + super(EXCEPTION_TYPE, Component.literal(message)); + } +}