From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 22 Aug 2021 15:21:57 -0700 Subject: [PATCH] Fix entity type tags suggestions in selectors This would really be better as a client fix because just to fix it all EntityArguments have been told to ask the server for completions when if this was fixed on the client, that wouldn't be needed. Mojira Issue: https://bugs.mojang.com/browse/MC-235045 diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java index 3ad9f1327cd99e16e8eca86d72cb8a57f28b245e..0148cadbeb41a882a05d982f0b34770b2829a04a 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -366,4 +366,20 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy return this.source.getBukkitSender(this); } // CraftBukkit end + // Paper start - override getSelectedEntities + @Override + public Collection getSelectedEntities() { + if (io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && this.source instanceof ServerPlayer player) { + double pickDistance = player.gameMode.getGameModeForPlayer().isCreative() ? 5.0F : 4.5F; + Vec3 min = player.getEyePosition(1.0F); + Vec3 viewVector = player.getViewVector(1.0F); + Vec3 max = min.add(viewVector.x * pickDistance, viewVector.y * pickDistance, viewVector.z * pickDistance); + net.minecraft.world.phys.AABB aabb = player.getBoundingBox().expandTowards(viewVector.scale(pickDistance)).inflate(1.0D, 1.0D, 1.0D); + pickDistance = player.gameMode.getGameModeForPlayer().isCreative() ? 6.0F : pickDistance; + net.minecraft.world.phys.EntityHitResult hitResult = net.minecraft.world.entity.projectile.ProjectileUtil.getEntityHitResult(player, min, max, aabb, (e) -> !e.isSpectator() && e.isPickable(), pickDistance); + return hitResult != null ? java.util.Collections.singletonList(hitResult.getEntity().getStringUUID()) : SharedSuggestionProvider.super.getSelectedEntities(); + } + return SharedSuggestionProvider.super.getSelectedEntities(); + } + // Paper end } diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java index af00f7dcbc1c4fb8da25128d5603b3ef041db7da..ea5f0600d47b0f7c08b96eed91e5de255114637b 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java @@ -411,6 +411,7 @@ public class Commands { private void fillUsableCommands(CommandNode tree, CommandNode result, CommandSourceStack source, Map, CommandNode> resultNodes) { Iterator iterator = tree.getChildren().iterator(); + boolean registeredAskServerSuggestionsForTree = false; // Paper - tell clients to ask server for suggestions for EntityArguments while (iterator.hasNext()) { CommandNode commandnode2 = (CommandNode) iterator.next(); if ( !org.spigotmc.SpigotConfig.sendNamespaced && commandnode2.getName().contains( ":" ) ) continue; // Spigot @@ -432,6 +433,12 @@ public class Commands { if (requiredargumentbuilder.getSuggestionsProvider() != null) { requiredargumentbuilder.suggests(SuggestionProviders.safelySwap(requiredargumentbuilder.getSuggestionsProvider())); + // Paper start - tell clients to ask server for suggestions for EntityArguments + registeredAskServerSuggestionsForTree = requiredargumentbuilder.getSuggestionsProvider() == net.minecraft.commands.synchronization.SuggestionProviders.ASK_SERVER; + } else if (io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && !registeredAskServerSuggestionsForTree && requiredargumentbuilder.getType() instanceof net.minecraft.commands.arguments.EntityArgument) { + requiredargumentbuilder.suggests(requiredargumentbuilder.getType()::listSuggestions); + registeredAskServerSuggestionsForTree = true; // You can only + // Paper end - tell clients to ask server for suggestions for EntityArguments } } diff --git a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java index 850db283bf12345e9e7d7e8e590dbe8135c6dce1..a2ea64b7ec5f47224312a1e08dd64347be6f7c43 100644 --- a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java +++ b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java @@ -128,7 +128,7 @@ public class EntityArgument implements ArgumentType { StringReader stringreader = new StringReader(suggestionsbuilder.getInput()); stringreader.setCursor(suggestionsbuilder.getStart()); - EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2)); + EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper try { argumentparserselector.parse(); diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java index ad99d67af92cda03beb1142b02082ee1bfc8a64a..a57ae219d57ed47baedfb73b3d815f39d4f87035 100644 --- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java +++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java @@ -115,12 +115,19 @@ public class EntitySelectorParser { private boolean hasScores; private boolean hasAdvancements; private boolean usesSelectors; + public boolean parsingEntityArgumentSuggestions; // Paper - track when parsing EntityArgument suggestions public EntitySelectorParser(StringReader reader) { this(reader, true); } public EntitySelectorParser(StringReader reader, boolean atAllowed) { + // Paper start + this(reader, atAllowed, false); + } + public EntitySelectorParser(StringReader reader, boolean atAllowed, boolean parsingEntityArgumentSuggestions) { + this.parsingEntityArgumentSuggestions = parsingEntityArgumentSuggestions; + // Paper end this.distance = MinMaxBounds.Doubles.ANY; this.level = MinMaxBounds.Ints.ANY; this.rotX = WrappedMinMaxBounds.ANY; diff --git a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java index c2b26a089c423e5df9a5cbfd1c70efbd1acb0e7a..f2376374c4c6efdfd5cfcea4d30c4b8b4dbbb0d5 100644 --- a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java +++ b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java @@ -67,6 +67,19 @@ public class EntitySelectorOptions { public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType((entity) -> { return Component.translatable("argument.entity.options.type.invalid", entity); }); + // Paper start + public static final DynamicCommandExceptionType ERROR_ENTITY_TAG_INVALID = new DynamicCommandExceptionType((object) -> { + return io.papermc.paper.adventure.PaperAdventure + .asVanilla(net.kyori.adventure.text.Component + .text("Invalid or unknown entity type tag '" + object + "'") + .hoverEvent(net.kyori.adventure.text.event.HoverEvent + .showText(net.kyori.adventure.text.Component + .text("You can disable this error in 'paper.yml'") + ) + ) + ); + }); + // Paper end private static void register(String id, EntitySelectorOptions.Modifier handler, Predicate condition, Component description) { OPTIONS.put(id, new EntitySelectorOptions.Option(handler, condition, description)); @@ -314,6 +327,12 @@ public class EntitySelectorOptions { if (reader.isTag()) { TagKey> tagKey = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, ResourceLocation.read(reader.getReader())); + // Paper start - throw error if invalid entity tag (only on suggestions to keep cmd success behavior) + if (reader.parsingEntityArgumentSuggestions && io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && !Registry.ENTITY_TYPE.isKnownTagName(tagKey)) { + reader.getReader().setCursor(i); + throw ERROR_ENTITY_TAG_INVALID.createWithContext(reader.getReader(), tagKey); + } + // Paper end reader.addPredicate((entity) -> { return entity.getType().is(tagKey) != bl; });