--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -2,11 +2,13 @@
 
 import com.mojang.brigadier.CommandDispatcher;
 import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 import com.mojang.brigadier.exceptions.CommandSyntaxException;
 import java.util.Collection;
+import java.util.Iterator;
 import net.minecraft.commands.CommandBuildContext;
 import net.minecraft.commands.CommandSourceStack;
-import net.minecraft.commands.Commands;
 import net.minecraft.commands.arguments.EntityArgument;
 import net.minecraft.commands.arguments.item.ItemArgument;
 import net.minecraft.commands.arguments.item.ItemInput;
@@ -15,91 +17,107 @@
 import net.minecraft.sounds.SoundEvents;
 import net.minecraft.sounds.SoundSource;
 import net.minecraft.world.entity.item.ItemEntity;
+import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.ItemStack;
 
 public class GiveCommand {
+
     public static final int MAX_ALLOWED_ITEMSTACKS = 100;
 
+    public GiveCommand() {}
+
     public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandRegistryAccess) {
-        dispatcher.register(
-            Commands.literal("give")
-                .requires(source -> source.hasPermission(2))
-                .then(
-                    Commands.argument("targets", EntityArgument.players())
-                        .then(
-                            Commands.argument("item", ItemArgument.item(commandRegistryAccess))
-                                .executes(
-                                    context -> giveItem(
-                                            context.getSource(), ItemArgument.getItem(context, "item"), EntityArgument.getPlayers(context, "targets"), 1
-                                        )
-                                )
-                                .then(
-                                    Commands.argument("count", IntegerArgumentType.integer(1))
-                                        .executes(
-                                            context -> giveItem(
-                                                    context.getSource(),
-                                                    ItemArgument.getItem(context, "item"),
-                                                    EntityArgument.getPlayers(context, "targets"),
-                                                    IntegerArgumentType.getInteger(context, "count")
-                                                )
-                                        )
-                                )
-                        )
+        dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("give").requires((commandlistenerwrapper) -> {
+            return commandlistenerwrapper.hasPermission(2);
+        })).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players()).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("item", ItemArgument.item(commandRegistryAccess)).executes((commandcontext) -> {
+            return GiveCommand.giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), 1);
+        })).then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((commandcontext) -> {
+            return GiveCommand.giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), IntegerArgumentType.getInteger(commandcontext, "count"));
+        })))));
+        // Paper start - support component removals with a custom pgive command
+        final com.mojang.brigadier.tree.CommandNode<net.minecraft.commands.CommandSourceStack> node = net.minecraft.commands.Commands
+            .literal("pgive").requires((css) ->  css.hasPermission(2))
+            .then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players())
+                .then(net.minecraft.commands.Commands.argument("item", new ItemArgument(commandRegistryAccess, true)).executes((ctx) -> {
+                    return GiveCommand.giveItem(ctx.getSource(), ItemArgument.getItem(ctx, "item"), EntityArgument.getPlayers(ctx, "targets"), 1);
+                })
+                    .then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((ctx) -> {
+                        return GiveCommand.giveItem(ctx.getSource(), ItemArgument.getItem(ctx, "item"), EntityArgument.getPlayers(ctx, "targets"), IntegerArgumentType.getInteger(ctx, "count"));
+                    }))
                 )
-        );
+            ).build();
+        setClientNodes(node);
+        dispatcher.getRoot().addChild(node);
+    }
+    static void setClientNodes(com.mojang.brigadier.tree.CommandNode<net.minecraft.commands.CommandSourceStack> node) {
+        if (node instanceof com.mojang.brigadier.tree.ArgumentCommandNode<net.minecraft.commands.CommandSourceStack,?> argumentNode) {
+            if (argumentNode.getType() instanceof ItemArgument) {
+                node.clientNode = new com.mojang.brigadier.tree.ArgumentCommandNode<>(
+                    argumentNode.getName(),
+                    com.mojang.brigadier.arguments.StringArgumentType.greedyString(),
+                    argumentNode.getCommand(),
+                    argumentNode.getRequirement(),
+                    argumentNode.getRedirect(),
+                    argumentNode.getRedirectModifier(),
+                    argumentNode.isFork(),
+                    (ctx, builder) -> builder.buildFuture()
+                );
+            }
+        }
+        node.getChildren().forEach(GiveCommand::setClientNodes);
+        // Paper end - support component removals with a custom pgive command
     }
 
     private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
-        ItemStack itemStack = item.createItemStack(1, false);
-        int i = itemStack.getMaxStackSize();
-        int j = i * 100;
-        if (count > j) {
-            source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", j, itemStack.getDisplayName()));
+        ItemStack itemstack = item.createItemStack(1, false);
+        final Component displayName = itemstack.getDisplayName(); // Paper - get display name early
+        int j = itemstack.getMaxStackSize();
+        int k = j * 100;
+
+        if (count > k) {
+            source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", k, itemstack.getDisplayName()));
             return 0;
         } else {
-            for (ServerPlayer serverPlayer : targets) {
-                int k = count;
+            Iterator iterator = targets.iterator();
 
-                while (k > 0) {
-                    int l = Math.min(i, k);
-                    k -= l;
-                    ItemStack itemStack2 = item.createItemStack(l, false);
-                    boolean bl = serverPlayer.getInventory().add(itemStack2);
-                    if (bl && itemStack2.isEmpty()) {
-                        ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false);
-                        if (itemEntity2 != null) {
-                            itemEntity2.makeFakeItem();
+            while (iterator.hasNext()) {
+                ServerPlayer entityplayer = (ServerPlayer) iterator.next();
+                int l = count;
+
+                while (l > 0) {
+                    int i1 = Math.min(j, l);
+
+                    l -= i1;
+                    ItemStack itemstack1 = item.createItemStack(i1, false);
+                    boolean flag = entityplayer.getInventory().add(itemstack1);
+                    ItemEntity entityitem;
+
+                    if (flag && itemstack1.isEmpty()) {
+                        entityitem = entityplayer.drop(itemstack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event
+                        if (entityitem != null) {
+                            entityitem.makeFakeItem();
                         }
 
-                        serverPlayer.level()
-                            .playSound(
-                                null,
-                                serverPlayer.getX(),
-                                serverPlayer.getY(),
-                                serverPlayer.getZ(),
-                                SoundEvents.ITEM_PICKUP,
-                                SoundSource.PLAYERS,
-                                0.2F,
-                                ((serverPlayer.getRandom().nextFloat() - serverPlayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F
-                            );
-                        serverPlayer.containerMenu.broadcastChanges();
+                        entityplayer.level().playSound((Player) null, entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((entityplayer.getRandom().nextFloat() - entityplayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F);
+                        entityplayer.containerMenu.broadcastChanges();
                     } else {
-                        ItemEntity itemEntity = serverPlayer.drop(itemStack2, false);
-                        if (itemEntity != null) {
-                            itemEntity.setNoPickUpDelay();
-                            itemEntity.setTarget(serverPlayer.getUUID());
+                        entityitem = entityplayer.drop(itemstack1, false);
+                        if (entityitem != null) {
+                            entityitem.setNoPickUpDelay();
+                            entityitem.setTarget(entityplayer.getUUID());
                         }
                     }
                 }
             }
 
             if (targets.size() == 1) {
-                source.sendSuccess(
-                    () -> Component.translatable("commands.give.success.single", count, itemStack.getDisplayName(), targets.iterator().next().getDisplayName()),
-                    true
-                );
+                source.sendSuccess(() -> {
+                    return Component.translatable("commands.give.success.single", count, displayName, ((ServerPlayer) targets.iterator().next()).getDisplayName()); // Paper - use cached display name
+                }, true);
             } else {
-                source.sendSuccess(() -> Component.translatable("commands.give.success.single", count, itemStack.getDisplayName(), targets.size()), true);
+                source.sendSuccess(() -> {
+                    return Component.translatable("commands.give.success.single", count, displayName, targets.size()); // Paper - use cached display name
+                }, true);
             }
 
             return targets.size();
