Paper/Spigot-Server-Patches/0464-Implement-Brigadier-Mojang-API.patch
Aikar 64ed429884
(FIRST 1.16.3): Update Paper to 1.16.3
This is a pretty tiny update with very little changed. Recommended to update
from 1.16.2 ASAP as 1.16.2 is now no longer supported.

Plugins should mostly remain working as the NMS revision did not change.
2020-09-10 19:47:58 -04:00

140 lines
9.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 19 Apr 2020 18:15:29 -0400
Subject: [PATCH] Implement Brigadier Mojang API
Adds AsyncPlayerSendCommandsEvent
- Allows modifying on a per command basis what command data they see.
Adds CommandRegisteredEvent
- Allows manipulating the CommandNode to add more children/metadata for the client
diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java
index 4b1ea9bc39191e01f83577c7bad128cf1ab9612f..22d748008d24fd6ed7cd8c4914e2ceb378f32c95 100644
--- a/src/main/java/net/minecraft/server/CommandDispatcher.java
+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java
@@ -270,6 +270,7 @@ public class CommandDispatcher {
bukkit.add(node.getName());
}
// Paper start - Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandListenerWrapper>(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper
MinecraftServer.getServer().execute(() -> {
runSync(entityplayer, bukkit, rootcommandnode);
});
@@ -277,6 +278,7 @@ public class CommandDispatcher {
private void runSync(EntityPlayer entityplayer, Collection<String> bukkit, RootCommandNode<ICompletionProvider> rootcommandnode) {
// Paper end - Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandListenerWrapper>(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper
PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit));
event.getPlayer().getServer().getPluginManager().callEvent(event);
diff --git a/src/main/java/net/minecraft/server/CommandListenerWrapper.java b/src/main/java/net/minecraft/server/CommandListenerWrapper.java
index 54a1988341a4a6e80ab40624280b7c92532d5db6..7073d697a5d35b9b72ea05d5608438ac3e54c20d 100644
--- a/src/main/java/net/minecraft/server/CommandListenerWrapper.java
+++ b/src/main/java/net/minecraft/server/CommandListenerWrapper.java
@@ -16,7 +16,7 @@ import java.util.function.BinaryOperator;
import java.util.stream.Stream;
import javax.annotation.Nullable;
-public class CommandListenerWrapper implements ICompletionProvider {
+public class CommandListenerWrapper implements ICompletionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper
public static final SimpleCommandExceptionType a = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.player"));
public static final SimpleCommandExceptionType b = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.entity"));
@@ -128,6 +128,25 @@ public class CommandListenerWrapper implements ICompletionProvider {
return this.g;
}
+ // Paper start
+ @Override
+ public org.bukkit.entity.Entity getBukkitEntity() {
+ return getEntity() != null ? getEntity().getBukkitEntity() : null;
+ }
+
+ @Override
+ public org.bukkit.World getBukkitWorld() {
+ return getWorld() != null ? getWorld().getWorld() : null;
+ }
+
+ @Override
+ public org.bukkit.Location getBukkitLocation() {
+ Vec3D pos = getPosition();
+ org.bukkit.World world = getBukkitWorld();
+ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null;
+ }
+ // Paper end
+
@Override
public boolean hasPermission(int i) {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index c7d88d9c190f0604189e6bfabc0250453b1a68c9..256ee3f8d8ef5a8e5b2a833b66c10e906de75b2c 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -579,8 +579,12 @@ public class PlayerConnection implements PacketListenerPlayIn {
ParseResults<CommandListenerWrapper> parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener());
this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions));
+ // Paper start
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer);
+ suggestEvent.setCancelled(suggestions.isEmpty());
+ if (!suggestEvent.callEvent()) return;
+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper
+ // Paper end
});
});
}
@@ -589,7 +593,11 @@ public class PlayerConnection implements PacketListenerPlayIn {
builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1);
completions.forEach(builder::suggest);
- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join()));
+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join();
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer);
+ suggestEvent.setCancelled(suggestions.isEmpty());
+ if (!suggestEvent.callEvent()) return;
+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestEvent.getSuggestions()));
}
// Paper end - async tab completion
}
diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java
index 5f33c9e52ac51486d4b22a6dcbfac7f46e0412bb..e16ecdea7d27424053b3f21378af054b2f808eca 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java
@@ -17,7 +17,7 @@ import net.minecraft.server.CommandListenerWrapper;
import org.bukkit.command.Command;
import org.bukkit.craftbukkit.CraftServer;
-public class BukkitCommandWrapper implements com.mojang.brigadier.Command<CommandListenerWrapper>, Predicate<CommandListenerWrapper>, SuggestionProvider<CommandListenerWrapper> {
+public class BukkitCommandWrapper implements com.mojang.brigadier.Command<CommandListenerWrapper>, Predicate<CommandListenerWrapper>, SuggestionProvider<CommandListenerWrapper>, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand<CommandListenerWrapper> { // Paper
private final CraftServer server;
private final Command command;
@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command<Comman
}
public LiteralCommandNode<CommandListenerWrapper> register(CommandDispatcher<CommandListenerWrapper> dispatcher, String label) {
- return dispatcher.register(
- LiteralArgumentBuilder.<CommandListenerWrapper>literal(label).requires(this).executes(this)
- .then(RequiredArgumentBuilder.<CommandListenerWrapper, String>argument("args", StringArgumentType.greedyString()).suggests(this).executes(this))
- );
+ // Paper start - Expose Brigadier to Paper-MojangAPI
+ com.mojang.brigadier.tree.RootCommandNode<CommandListenerWrapper> root = dispatcher.getRoot();
+ LiteralCommandNode<CommandListenerWrapper> literal = LiteralArgumentBuilder.<CommandListenerWrapper>literal(label).requires(this).executes(this).build();
+ com.mojang.brigadier.tree.ArgumentCommandNode<CommandListenerWrapper, String> defaultArgs = RequiredArgumentBuilder.<CommandListenerWrapper, String>argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build();
+ literal.addChild(defaultArgs);
+ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<CommandListenerWrapper> event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs);
+ if (!event.callEvent()) {
+ return null;
+ }
+ literal = event.getLiteral();
+ root.addChild(literal);
+ return literal;
+ // Paper end
}
@Override