mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-11 09:23:42 +01:00
219 lines
13 KiB
Diff
219 lines
13 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||
|
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 {
|