diff options
Diffstat (limited to 'patches/server/1042-Add-experimental-improved-give-command.patch')
-rw-r--r-- | patches/server/1042-Add-experimental-improved-give-command.patch | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/patches/server/1042-Add-experimental-improved-give-command.patch b/patches/server/1042-Add-experimental-improved-give-command.patch new file mode 100644 index 0000000000..670050a507 --- /dev/null +++ b/patches/server/1042-Add-experimental-improved-give-command.patch @@ -0,0 +1,218 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +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 d76296c6d53065aecb010d8ea682c9acd7365f17..4c3749deebb7d5c35f3977814f1d7b0307198b1e 100644 +--- a/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java ++++ b/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java +@@ -16,7 +16,12 @@ public class ItemArgument implements ArgumentType<ItemInput> { + 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) { +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 3d24fbca90bc7d8bdbac1be2176555c15ae75039..94ea5f0b1913ffa03794d231a6768dd786dc9697 100644 +--- a/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java ++++ b/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java +@@ -25,8 +25,15 @@ public class ItemInput { + ); + private final Holder<Item> item; + private final DataComponentMap components; ++ @javax.annotation.Nullable private final net.minecraft.core.component.DataComponentPatch patch; // Paper + + public ItemInput(Holder<Item> item, DataComponentMap components) { ++ // Paper start ++ this(item, components, null); ++ } ++ public ItemInput(Holder<Item> item, DataComponentMap components, @javax.annotation.Nullable final net.minecraft.core.component.DataComponentPatch patch) { ++ this.patch = patch; ++ // Paper end + this.item = item; + this.components = components; + } +@@ -37,7 +44,13 @@ 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 5347a96be3bfbbd2963747ba4b5f222215d80371..f306c27f3242084f2cc39393e302bbdd0b228db2 100644 +--- a/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java ++++ b/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java +@@ -59,8 +59,15 @@ public class ItemParser { + static final Function<SuggestionsBuilder, CompletableFuture<Suggestions>> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture; + final HolderLookup.RegistryLookup<Item> items; + final DynamicOps<Tag> 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); + } +@@ -68,6 +75,7 @@ public class ItemParser { + public ItemParser.ItemResult parse(StringReader reader) throws CommandSyntaxException { + final MutableObject<Holder<Item>> 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> item) { +@@ -77,12 +85,19 @@ public class ItemParser { + @Override + public <T> void visitComponent(DataComponentType<T> type, T value) { + builder.set(type, value); ++ // Paper start - support component removals ++ patchBuilder.set(type, value); ++ } ++ @Override ++ public <T> void visitComponentRemove(final DataComponentType<T> type) { ++ patchBuilder.remove(type); ++ // Paper end - support component removals + } + }); + Holder<Item> 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> item, DataComponentMap components) throws CommandSyntaxException { +@@ -116,7 +131,7 @@ public class ItemParser { + return suggestionsVisitor.resolveSuggestions(builder, stringReader); + } + +- public static record ItemResult(Holder<Item> item, DataComponentMap components) { ++ public static record ItemResult(Holder<Item> item, DataComponentMap components, @javax.annotation.Nullable net.minecraft.core.component.DataComponentPatch patch) { // Paper + } + + class State { +@@ -154,17 +169,28 @@ 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() != ',') { +@@ -239,12 +265,18 @@ public class ItemParser { + } + + private CompletableFuture<Suggestions> suggestComponentAssignment(SuggestionsBuilder builder) { ++ // Paper start - support component removals ++ return this.suggestComponentAssignment(builder, true); ++ } ++ private CompletableFuture<Suggestions> suggestComponentAssignment(SuggestionsBuilder builder, boolean suggestRemove) { ++ if (suggestRemove) builder.suggest("!", Component.literal("Remove a data component")); ++ // Paper end - support component removals + String string = builder.getRemaining().toLowerCase(Locale.ROOT); + 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(); +@@ -270,6 +302,7 @@ public class ItemParser { + + default <T> void visitComponent(DataComponentType<T> type, T value) { + } ++ default <T> void visitComponentRemove(DataComponentType<T> type) {} // Paper + + default void visitSuggestions(Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestor) { + } +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java +index 0d9de4c61c7b26a6ff37c12fde629161fd0c3d5a..c738bbfa73888a0caed507e02f5c113f681e5cc2 100644 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -34,6 +34,38 @@ 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<net.minecraft.commands.CommandSourceStack> node = net.minecraft.commands.Commands ++ .literal("pgive").requires((commandlistenerwrapper) -> commandlistenerwrapper.hasPermission(2)) ++ .then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players()) ++ .then(net.minecraft.commands.Commands.argument("item", new ItemArgument(commandRegistryAccess, true)).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")); ++ })) ++ ) ++ ).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 { |