From 7289589315c76ecd3e1498c5e8ffd6854f578cc3 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Fri, 14 Jun 2024 11:59:44 +0200 Subject: [PATCH] 988 --- ...g-for-mobs-immune-to-default-effects.patch | 0 .../Add-missing-fishing-event-state.patch | 0 ...d-API-to-get-player-ha-proxy-address.patch | 0 .../server/Adopt-MaterialRerouting.patch | 0 ...plugin-to-use-Paper-PluginLoader-API.patch | 0 .../server/Brigadier-based-command-API.patch | 6 +- patches/server/Chunk-Save-Reattempt.patch | 4 +- .../server/Deep-clone-nbt-tags-in-PDC.patch | 0 ...cate-InvAction-HOTBAR_MOVE_AND_READD.patch | 0 ...-removed-data-components-in-ItemMeta.patch | 0 .../Expose-hasColor-to-leather-armor.patch | 0 .../server/Fix-ItemFlags.patch | 2 +- ...ing-BlockPlaceEvent-calling-onRemove.patch | 0 .../Fix-equipment-slot-and-group-API.patch | 0 ...met-damage-reduction-inconsistencies.patch | 0 .../server/Fix-issues-with-Recipe-API.patch | 0 ...onnect-packet-in-phases-where-it-doe.patch | 0 .../Fix-shield-disable-inconsistency.patch | 4 +- ...re-disarming-not-working-as-intended.patch | 0 .../server/General-ItemMeta-fixes.patch | 10 +- ...e-Large-Packets-disconnecting-client.patch | 0 .../server/More-Chest-Block-API.patch | 0 ...-data-to-disk-if-it-serializes-witho.patch | 6 +- ...ent-NPE-if-hooked-entity-was-cleared.patch | 0 ...oversized-item-data-in-equipment-and.patch | 0 ...ata-component-type-on-encoding-error.patch | 0 ...and-End-Portal-Frames-from-being-des.patch | 0 ...a-handling-of-LivingEntity-actuallyH.patch | 0 ...egionFileCache-and-make-configurable.patch | 2 +- .../Support-old-UUID-format-for-NBT.patch | 0 ...ve-checking-handled-tags-in-itemmeta.patch | 2 + ...d-experimental-improved-give-command.patch | 255 ------------------ 32 files changed, 19 insertions(+), 272 deletions(-) rename patches/{unapplied => }/server/Add-config-for-mobs-immune-to-default-effects.patch (100%) rename patches/{unapplied => }/server/Add-missing-fishing-event-state.patch (100%) rename patches/{unapplied => }/server/Added-API-to-get-player-ha-proxy-address.patch (100%) rename patches/{unapplied => }/server/Adopt-MaterialRerouting.patch (100%) rename patches/{unapplied => }/server/Allow-Bukkit-plugin-to-use-Paper-PluginLoader-API.patch (100%) rename patches/{unapplied => }/server/Brigadier-based-command-API.patch (99%) rename patches/{unapplied => }/server/Deep-clone-nbt-tags-in-PDC.patch (100%) rename patches/{unapplied => }/server/Deprecate-InvAction-HOTBAR_MOVE_AND_READD.patch (100%) rename patches/{unapplied => }/server/Don-t-lose-removed-data-components-in-ItemMeta.patch (100%) rename patches/{unapplied => }/server/Expose-hasColor-to-leather-armor.patch (100%) rename patches/{unapplied => }/server/Fix-ItemFlags.patch (98%) rename patches/{unapplied => }/server/Fix-cancelling-BlockPlaceEvent-calling-onRemove.patch (100%) rename patches/{unapplied => }/server/Fix-equipment-slot-and-group-API.patch (100%) rename patches/{unapplied => }/server/Fix-helmet-damage-reduction-inconsistencies.patch (100%) rename patches/{unapplied => }/server/Fix-issues-with-Recipe-API.patch (100%) rename patches/{unapplied => }/server/Fix-sending-disconnect-packet-in-phases-where-it-doe.patch (100%) rename patches/{unapplied => }/server/Fix-shield-disable-inconsistency.patch (79%) rename patches/{unapplied => }/server/Fix-tripwire-disarming-not-working-as-intended.patch (100%) rename patches/{unapplied => }/server/General-ItemMeta-fixes.patch (99%) rename patches/{unapplied => }/server/Handle-Large-Packets-disconnecting-client.patch (100%) rename patches/{unapplied => }/server/More-Chest-Block-API.patch (100%) rename patches/{unapplied => }/server/Prevent-NPE-if-hooked-entity-was-cleared.patch (100%) rename patches/{unapplied => }/server/Prevent-sending-oversized-item-data-in-equipment-and.patch (100%) rename patches/{unapplied => }/server/Print-data-component-type-on-encoding-error.patch (100%) rename patches/{unapplied => }/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch (100%) rename patches/{unapplied => }/server/Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch (100%) rename patches/{unapplied => }/server/Support-old-UUID-format-for-NBT.patch (100%) rename patches/{unapplied => }/server/improve-checking-handled-tags-in-itemmeta.patch (99%) delete mode 100644 patches/unapplied/server/Add-experimental-improved-give-command.patch diff --git a/patches/unapplied/server/Add-config-for-mobs-immune-to-default-effects.patch b/patches/server/Add-config-for-mobs-immune-to-default-effects.patch similarity index 100% rename from patches/unapplied/server/Add-config-for-mobs-immune-to-default-effects.patch rename to patches/server/Add-config-for-mobs-immune-to-default-effects.patch diff --git a/patches/unapplied/server/Add-missing-fishing-event-state.patch b/patches/server/Add-missing-fishing-event-state.patch similarity index 100% rename from patches/unapplied/server/Add-missing-fishing-event-state.patch rename to patches/server/Add-missing-fishing-event-state.patch diff --git a/patches/unapplied/server/Added-API-to-get-player-ha-proxy-address.patch b/patches/server/Added-API-to-get-player-ha-proxy-address.patch similarity index 100% rename from patches/unapplied/server/Added-API-to-get-player-ha-proxy-address.patch rename to patches/server/Added-API-to-get-player-ha-proxy-address.patch diff --git a/patches/unapplied/server/Adopt-MaterialRerouting.patch b/patches/server/Adopt-MaterialRerouting.patch similarity index 100% rename from patches/unapplied/server/Adopt-MaterialRerouting.patch rename to patches/server/Adopt-MaterialRerouting.patch diff --git a/patches/unapplied/server/Allow-Bukkit-plugin-to-use-Paper-PluginLoader-API.patch b/patches/server/Allow-Bukkit-plugin-to-use-Paper-PluginLoader-API.patch similarity index 100% rename from patches/unapplied/server/Allow-Bukkit-plugin-to-use-Paper-PluginLoader-API.patch rename to patches/server/Allow-Bukkit-plugin-to-use-Paper-PluginLoader-API.patch diff --git a/patches/unapplied/server/Brigadier-based-command-API.patch b/patches/server/Brigadier-based-command-API.patch similarity index 99% rename from patches/unapplied/server/Brigadier-based-command-API.patch rename to patches/server/Brigadier-based-command-API.patch index e9ec61aafd..37bef66ff4 100644 --- a/patches/unapplied/server/Brigadier-based-command-API.patch +++ b/patches/server/Brigadier-based-command-API.patch @@ -2152,7 +2152,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + resultNodes.keySet().removeIf((node) -> !org.spigotmc.SpigotConfig.sendNamespaced && node.getName().contains( ":" )); // Paper - Remove namedspaced from result nodes to prevent redirect trimming ~ see comment below Iterator iterator = tree.getChildren().iterator(); - boolean registeredAskServerSuggestionsForTree = false; // Paper - tell clients to ask server for suggestions for EntityArguments + while (iterator.hasNext()) { @@ -0,0 +0,0 @@ public class Commands { if (commandnode2.canUse(source)) { @@ -2222,7 +2222,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public int autosavePeriod; - public Commands vanillaCommandDispatcher; + // Paper - don't store the vanilla dispatcher - public boolean forceTicks; // Paper + private boolean forceTicks; // CraftBukkit end // Spigot start @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entry : this.attributeModifiers.entries()) { - Preconditions.checkArgument(!(entry.getValue().getUniqueId().equals(modifier.getUniqueId()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper + Preconditions.checkArgument(!entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute, "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine } + } // Paper + this.checkAttributeList(); // Paper - moved down @@ -1062,8 +1062,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 && (Objects.equals(this.customTag, that.customTag)) && (this.persistentDataContainer.equals(that.persistentDataContainer)) @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); + hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); hash = 61 * hash + (this.hasDamage() ? this.damage : 0); - hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); - hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); @@ -1433,7 +1433,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void setEatSeconds(float eatSeconds) { + Preconditions.checkArgument(eatSeconds > 0, "Eat seconds must be positive"); // Paper - validate eat_seconds - this.handle = new FoodProperties(this.handle.nutrition(), this.handle.saturation(), this.handle.canAlwaysEat(), eatSeconds, this.handle.effects()); + this.handle = new FoodProperties(this.handle.nutrition(), this.handle.saturation(), this.handle.canAlwaysEat(), eatSeconds, this.handle.usingConvertsTo(), this.handle.effects()); } @@ -0,0 +0,0 @@ public final class CraftFoodComponent implements FoodComponent { diff --git a/patches/unapplied/server/Handle-Large-Packets-disconnecting-client.patch b/patches/server/Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from patches/unapplied/server/Handle-Large-Packets-disconnecting-client.patch rename to patches/server/Handle-Large-Packets-disconnecting-client.patch diff --git a/patches/unapplied/server/More-Chest-Block-API.patch b/patches/server/More-Chest-Block-API.patch similarity index 100% rename from patches/unapplied/server/More-Chest-Block-API.patch rename to patches/server/More-Chest-Block-API.patch diff --git a/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch b/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch index 1c1103b17a..123e55847e 100644 --- a/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch +++ b/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch @@ -47,7 +47,7 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSto index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { +@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable { try { NbtIo.write(nbt, (DataOutput) dataoutputstream); @@ -66,7 +66,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } catch (Throwable throwable1) { throwable.addSuppressed(throwable1); } -@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { +@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable { throw throwable; } @@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // Paper start - Chunk save reattempt return; -@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { +@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable { public RegionStorageInfo info() { return this.info; } diff --git a/patches/unapplied/server/Prevent-NPE-if-hooked-entity-was-cleared.patch b/patches/server/Prevent-NPE-if-hooked-entity-was-cleared.patch similarity index 100% rename from patches/unapplied/server/Prevent-NPE-if-hooked-entity-was-cleared.patch rename to patches/server/Prevent-NPE-if-hooked-entity-was-cleared.patch diff --git a/patches/unapplied/server/Prevent-sending-oversized-item-data-in-equipment-and.patch b/patches/server/Prevent-sending-oversized-item-data-in-equipment-and.patch similarity index 100% rename from patches/unapplied/server/Prevent-sending-oversized-item-data-in-equipment-and.patch rename to patches/server/Prevent-sending-oversized-item-data-in-equipment-and.patch diff --git a/patches/unapplied/server/Print-data-component-type-on-encoding-error.patch b/patches/server/Print-data-component-type-on-encoding-error.patch similarity index 100% rename from patches/unapplied/server/Print-data-component-type-on-encoding-error.patch rename to patches/server/Print-data-component-type-on-encoding-error.patch diff --git a/patches/unapplied/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 100% rename from patches/unapplied/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch diff --git a/patches/unapplied/server/Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch b/patches/server/Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch similarity index 100% rename from patches/unapplied/server/Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch rename to patches/server/Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch diff --git a/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch index 2e96ad8b88..e2f67f1959 100644 --- a/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch +++ b/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch @@ -14,7 +14,7 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSto index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { +@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable { if (regionfile != null) { return regionfile; } else { diff --git a/patches/unapplied/server/Support-old-UUID-format-for-NBT.patch b/patches/server/Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/unapplied/server/Support-old-UUID-format-for-NBT.patch rename to patches/server/Support-old-UUID-format-for-NBT.patch diff --git a/patches/unapplied/server/improve-checking-handled-tags-in-itemmeta.patch b/patches/server/improve-checking-handled-tags-in-itemmeta.patch similarity index 99% rename from patches/unapplied/server/improve-checking-handled-tags-in-itemmeta.patch rename to patches/server/improve-checking-handled-tags-in-itemmeta.patch index 9f8222c16a..6440d1d2c7 100644 --- a/patches/unapplied/server/improve-checking-handled-tags-in-itemmeta.patch +++ b/patches/server/improve-checking-handled-tags-in-itemmeta.patch @@ -460,6 +460,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - CraftMetaItem.RARITY.TYPE, - CraftMetaItem.FOOD.TYPE, - CraftMetaItem.TOOL.TYPE, +- CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, - CraftMetaItem.DAMAGE.TYPE, - CraftMetaItem.MAX_DAMAGE.TYPE, - CraftMetaItem.CUSTOM_DATA.TYPE, @@ -519,6 +520,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + CraftMetaItem.RARITY.TYPE, + CraftMetaItem.FOOD.TYPE, + CraftMetaItem.TOOL.TYPE, ++ CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, + CraftMetaItem.DAMAGE.TYPE, + CraftMetaItem.MAX_DAMAGE.TYPE, + CraftMetaItem.CUSTOM_DATA.TYPE, diff --git a/patches/unapplied/server/Add-experimental-improved-give-command.patch b/patches/unapplied/server/Add-experimental-improved-give-command.patch deleted file mode 100644 index 1b02b54797..0000000000 --- a/patches/unapplied/server/Add-experimental-improved-give-command.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 26 Apr 2024 23:15:27 -0700 -Subject: [PATCH] Add experimental improved give command - -Supports removing data components from itemstacks - -diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java b/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java -+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java -@@ -0,0 +0,0 @@ public class ItemArgument implements ArgumentType { - private final ItemParser parser; - - public ItemArgument(CommandBuildContext commandRegistryAccess) { -- this.parser = new ItemParser(commandRegistryAccess); -+ // Paper start - support component removals -+ this(commandRegistryAccess, false); -+ } -+ public ItemArgument(CommandBuildContext commandRegistryAccess, boolean allowRemovals) { -+ this.parser = new ItemParser(commandRegistryAccess, allowRemovals); -+ // Paper end - support component removals - } - - public static ItemArgument item(CommandBuildContext commandRegistryAccess) { -@@ -0,0 +0,0 @@ public class ItemArgument implements ArgumentType { - - public ItemInput parse(StringReader stringReader) throws CommandSyntaxException { - ItemParser.ItemResult itemResult = this.parser.parse(stringReader); -- return new ItemInput(itemResult.item(), itemResult.components()); -+ return new ItemInput(itemResult.item(), itemResult.components(), itemResult.patch()); // Paper - support component removals - } - - public static ItemInput getItem(CommandContext context, String name) { -diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java b/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java -+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java -@@ -0,0 +0,0 @@ public class ItemInput { - ); - private final Holder item; - private final DataComponentMap components; -+ @javax.annotation.Nullable private final net.minecraft.core.component.DataComponentPatch patch; // Paper - - public ItemInput(Holder item, DataComponentMap components) { -+ // Paper start -+ this(item, components, null); -+ } -+ public ItemInput(Holder item, DataComponentMap components, @javax.annotation.Nullable final net.minecraft.core.component.DataComponentPatch patch) { -+ this.patch = patch; -+ // Paper end - this.item = item; - this.components = components; - } -@@ -0,0 +0,0 @@ public class ItemInput { - - public ItemStack createItemStack(int amount, boolean checkOverstack) throws CommandSyntaxException { - ItemStack itemStack = new ItemStack(this.item, amount); -- itemStack.applyComponents(this.components); -+ // Paper start - support component removals -+ if (this.patch != null) { -+ itemStack.applyComponents(this.patch); -+ } else { -+ itemStack.applyComponents(this.components); -+ } -+ // Paper end - support component removals - if (checkOverstack && amount > itemStack.getMaxStackSize()) { - throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize()); - } else { -diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java b/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java -+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java -@@ -0,0 +0,0 @@ public class ItemParser { - static final Function> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture; - final HolderLookup.RegistryLookup items; - final DynamicOps registryOps; -+ final boolean allowRemoves; // Paper - support component removals - - public ItemParser(HolderLookup.Provider registriesLookup) { -+ // Paper start - support component removals -+ this(registriesLookup, false); -+ } -+ public ItemParser(HolderLookup.Provider registriesLookup, boolean allowRemoves) { -+ this.allowRemoves = allowRemoves; -+ // Paper end - support component removals - this.items = registriesLookup.lookupOrThrow(Registries.ITEM); - this.registryOps = registriesLookup.createSerializationContext(NbtOps.INSTANCE); - } -@@ -0,0 +0,0 @@ public class ItemParser { - public ItemParser.ItemResult parse(StringReader reader) throws CommandSyntaxException { - final MutableObject> mutableObject = new MutableObject<>(); - final DataComponentMap.Builder builder = DataComponentMap.builder(); -+ final net.minecraft.core.component.DataComponentPatch.Builder patchBuilder = net.minecraft.core.component.DataComponentPatch.builder(); // Paper - support component removals - this.parse(reader, new ItemParser.Visitor() { - @Override - public void visitItem(Holder item) { -@@ -0,0 +0,0 @@ public class ItemParser { - @Override - public void visitComponent(DataComponentType type, T value) { - builder.set(type, value); -+ // Paper start - support component removals -+ patchBuilder.set(type, value); -+ } -+ @Override -+ public void visitComponentRemove(final DataComponentType type) { -+ patchBuilder.remove(type); -+ // Paper end - support component removals - } - }); - Holder holder = Objects.requireNonNull(mutableObject.getValue(), "Parser gave no item"); - DataComponentMap dataComponentMap = builder.build(); - validateComponents(reader, holder, dataComponentMap); -- return new ItemParser.ItemResult(holder, dataComponentMap); -+ return new ItemParser.ItemResult(holder, dataComponentMap, this.allowRemoves ? patchBuilder.build() : null); // Paper - support component removals - } - - private static void validateComponents(StringReader reader, Holder item, DataComponentMap components) throws CommandSyntaxException { -@@ -0,0 +0,0 @@ public class ItemParser { - return suggestionsVisitor.resolveSuggestions(builder, stringReader); - } - -- public static record ItemResult(Holder item, DataComponentMap components) { -+ public static record ItemResult(Holder item, DataComponentMap components, @javax.annotation.Nullable net.minecraft.core.component.DataComponentPatch patch) { // Paper - } - - class State { -@@ -0,0 +0,0 @@ public class ItemParser { - - while (this.reader.canRead() && this.reader.peek() != ']') { - this.reader.skipWhitespace(); -+ boolean removing = ItemParser.this.allowRemoves && this.reader.canRead() && this.reader.peek() == '!'; -+ if (removing) { -+ this.reader.skip(); -+ this.visitor.visitSuggestions(builder -> this.suggestComponentAssignment(builder, false)); -+ } - DataComponentType dataComponentType = readComponentType(this.reader); - if (!set.add(dataComponentType)) { - throw ItemParser.ERROR_REPEATED_COMPONENT.create(dataComponentType); - } - -+ // Paper start - support component removals -+ if (removing) { -+ this.visitor.visitComponentRemove(dataComponentType); -+ } else { -+ // Paper end - support component removals - this.visitor.visitSuggestions(this::suggestAssignment); - this.reader.skipWhitespace(); - this.reader.expect('='); - this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING); - this.reader.skipWhitespace(); - this.readComponent(dataComponentType); -+ } // Paper - support component removals - this.reader.skipWhitespace(); - this.visitor.visitSuggestions(this::suggestNextOrEndComponents); - if (!this.reader.canRead() || this.reader.peek() != ',') { -@@ -0,0 +0,0 @@ public class ItemParser { - } - - private CompletableFuture suggestComponentAssignment(SuggestionsBuilder builder) { -+ // Paper start - support component removals -+ return this.suggestComponentAssignment(builder, true); -+ } -+ private CompletableFuture suggestComponentAssignment(SuggestionsBuilder builder, boolean suggestRemove) { - String string = builder.getRemaining().toLowerCase(Locale.ROOT); -+ if (suggestRemove && string.isBlank()) builder.suggest("!", Component.literal("Remove a data component")); -+ // Paper end - support component removals - SharedSuggestionProvider.filterResources(BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet(), string, entry -> entry.getKey().location(), entry -> { - DataComponentType dataComponentType = entry.getValue(); - if (dataComponentType.codec() != null) { - ResourceLocation resourceLocation = entry.getKey().location(); -- builder.suggest(resourceLocation.toString() + "="); -+ builder.suggest(resourceLocation.toString() + (suggestRemove ? "=" : "")); // Paper - support component removals - } - }); - return builder.buildFuture(); -@@ -0,0 +0,0 @@ public class ItemParser { - - default void visitComponent(DataComponentType type, T value) { - } -+ default void visitComponentRemove(DataComponentType type) {} // Paper - - default void visitSuggestions(Function> suggestor) { - } -diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/GiveCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java -@@ -0,0 +0,0 @@ public class GiveCommand { - })).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 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 node) { -+ if (node instanceof com.mojang.brigadier.tree.ArgumentCommandNode 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 targets, int count) throws CommandSyntaxException { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java -@@ -0,0 +0,0 @@ public final class VanillaCommandWrapper extends BukkitCommand { - vanillaCommand = vanillaCommand.getRedirect(); - } - final String commandName = vanillaCommand.getName(); -+ if ("pgive".equals(stripDefaultNamespace(commandName))) { -+ return "bukkit.command.paper.pgive"; -+ } - return "minecraft.command." + stripDefaultNamespace(commandName); - } - -diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java -+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java -@@ -0,0 +0,0 @@ public class MinecraftCommandPermissionsTest extends AbstractTestingBase { - Set foundPerms = new HashSet<>(); - for (CommandNode child : root.getChildren()) { - final String vanillaPerm = VanillaCommandWrapper.getPermission(child); -+ if ("bukkit.command.paper.pgive".equals(vanillaPerm)) { // skip our custom give command -+ continue; -+ } - if (!perms.contains(vanillaPerm)) { - missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command"); - } else {