From ad6070dffd9bd5e46bd9d9d423a6d111a8af130a Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 31 Jan 2019 15:08:25 +1100 Subject: [PATCH] SPIGOT-4193: API for selecting entities by strings --- nms-patches/ArgumentEntity.patch | 19 ++++++ nms-patches/ArgumentParserSelector.patch | 63 +++++++++++++++++++ .../org/bukkit/craftbukkit/CraftServer.java | 21 +++++++ .../block/data/CraftBlockData.java | 2 +- .../command/VanillaCommandWrapper.java | 2 +- 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 nms-patches/ArgumentEntity.patch create mode 100644 nms-patches/ArgumentParserSelector.patch diff --git a/nms-patches/ArgumentEntity.patch b/nms-patches/ArgumentEntity.patch new file mode 100644 index 0000000000..0af88bf603 --- /dev/null +++ b/nms-patches/ArgumentEntity.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/server/ArgumentEntity.java ++++ b/net/minecraft/server/ArgumentEntity.java +@@ -84,9 +84,15 @@ + } + + public EntitySelector parse(StringReader stringreader) throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(stringreader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + boolean flag = false; + ArgumentParserSelector argumentparserselector = new ArgumentParserSelector(stringreader); +- EntitySelector entityselector = argumentparserselector.s(); ++ EntitySelector entityselector = argumentparserselector.s(overridePermissions); // CraftBukkit + + if (entityselector.a() > 1 && this.h) { + if (this.i) { diff --git a/nms-patches/ArgumentParserSelector.patch b/nms-patches/ArgumentParserSelector.patch new file mode 100644 index 0000000000..ebce87359d --- /dev/null +++ b/nms-patches/ArgumentParserSelector.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/server/ArgumentParserSelector.java ++++ b/net/minecraft/server/ArgumentParserSelector.java +@@ -98,8 +98,14 @@ + } + + public ArgumentParserSelector(StringReader stringreader, boolean flag) { +- this.q = CriterionConditionValue.c.e; +- this.r = CriterionConditionValue.d.e; ++ // CraftBukkit start - decompile error ++ try { ++ this.q = (CriterionConditionValue.c) Class.forName("net.minecraft.server.CriterionConditionValue$c").getDeclaredField("e").get(null); ++ this.r = (CriterionConditionValue.d) Class.forName("net.minecraft.server.CriterionConditionValue$d").getDeclaredField("e").get(null); ++ } catch (Exception ex) { ++ throw new AssertionError(ex); ++ } ++ // CraftBukkit end + this.y = CriterionConditionRange.a; + this.z = CriterionConditionRange.a; + this.A = (entity) -> { +@@ -126,7 +132,7 @@ + axisalignedbb = this.a(this.v == null ? 0.0D : this.v, this.w == null ? 0.0D : this.w, this.x == null ? 0.0D : this.x); + } + +- Function function; ++ Function function; // CraftBukkit - decompile error + + if (this.s == null && this.t == null && this.u == null) { + function = (vec3d) -> { +@@ -187,8 +193,10 @@ + }; + } + +- protected void b() throws CommandSyntaxException { +- this.T = true; ++ // CraftBukkit start ++ protected void b(boolean overridePermissions) throws CommandSyntaxException { ++ this.T = !overridePermissions; ++ // CraftBukkit end + this.G = this::d; + if (!this.l.canRead()) { + throw ArgumentParserSelector.d.createWithContext(this.l); +@@ -431,6 +439,12 @@ + } + + public EntitySelector s() throws CommandSyntaxException { ++ // CraftBukkit start ++ return s(false); ++ } ++ ++ public EntitySelector s(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.E = this.l.getCursor(); + this.G = this::b; + if (this.l.canRead() && this.l.peek() == '@') { +@@ -439,7 +453,7 @@ + } + + this.l.skip(); +- this.b(); ++ this.b(overridePermissions); // CraftBukkit + } else { + this.c(); + } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 6d026b70e8..5e2d2b6526 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -132,7 +132,9 @@ import com.google.common.collect.MapMaker; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.StringReader; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; @@ -1873,6 +1875,25 @@ public final class CraftServer implements Server { return new CraftLootTable(key, registry.getLootTable(CraftNamespacedKey.toMinecraft(key))); } + @Override + public List selectEntities(CommandSender sender, String selector) { + Preconditions.checkArgument(selector != null, "Selector cannot be null"); + Preconditions.checkArgument(sender != null, "Sender cannot be null"); + + ArgumentEntity arg = ArgumentEntity.b(); + List nms; + + try { + StringReader reader = new StringReader(selector); + nms = arg.parse(reader, true).b(VanillaCommandWrapper.getListener(sender)); + Preconditions.checkArgument(!reader.canRead(), "Spurious trailing data in selector: " + selector); + } catch (CommandSyntaxException ex) { + throw new IllegalArgumentException("Could not parse selector: " + selector, ex); + } + + return new ArrayList<>(Lists.transform(nms, (entity) -> entity.getBukkitEntity())); + } + @Deprecated @Override public UnsafeValues getUnsafe() { diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java index 8c110c67dd..7755e4f7a6 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java @@ -505,7 +505,7 @@ public class CraftBlockData implements BlockData { StringReader reader = new StringReader(data); ArgumentBlock arg = new ArgumentBlock(reader, false).a(false); - Preconditions.checkArgument(!reader.canRead(), "Spurious trailing data"); + Preconditions.checkArgument(!reader.canRead(), "Spurious trailing data: " + data); blockData = arg.getBlockData(); parsed = arg.getStateMap(); diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index 6e187250b1..59d82cf64a 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -63,7 +63,7 @@ public final class VanillaCommandWrapper extends BukkitCommand { return results; } - private CommandListenerWrapper getListener(CommandSender sender) { + public static CommandListenerWrapper getListener(CommandSender sender) { if (sender instanceof Player) { return ((CraftPlayer) sender).getHandle().getCommandListener(); }