@@ -2,12 +2,9 @@ package fr.pandacube.lib.paper.commands;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource ;
import com.mojang.brigadier.CommandDispatcher ;
import com.mojang.brigadier.LiteralMessage ;
import com.mojang.brigadier.arguments.ArgumentType ;
import com.mojang.brigadier.context.CommandContext ;
import com.mojang.brigadier.context.ParsedCommandNode ;
import com.mojang.brigadier.exceptions.CommandSyntaxException ;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType ;
import com.mojang.brigadier.suggestion.SuggestionProvider ;
import com.mojang.brigadier.tree.CommandNode ;
import com.mojang.brigadier.tree.LiteralCommandNode ;
@@ -15,7 +12,7 @@ import com.mojang.brigadier.tree.RootCommandNode;
import fr.pandacube.lib.chat.Chat ;
import fr.pandacube.lib.commands.BrigadierCommand ;
import fr.pandacube.lib.commands.SuggestionsSupplier ;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftNamespacedKey ;
import fr.pandacube.lib.paper.permissions.PandalibPaperPermissions ;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer ;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftVector ;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper ;
@@ -25,18 +22,14 @@ import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ComponentArgume
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Coordinates ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntityArgument ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.GameProfileArgument ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ResourceLocationArgument ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources.ResourceLocation ;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer ;
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure ;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper ;
import fr.pandacube.lib.util.Log ;
import net.kyori.adventure.text.Component ;
import org.bukkit.Bukkit ;
import org.bukkit.NamespacedKey ;
import org.bukkit.World ;
import org.bukkit.command.Command ;
import org.bukkit.command.CommandMap ;
@@ -55,200 +48,283 @@ import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.HashSet ;
import java.util.List ;
import java.util.Set ;
import java.util.function.Function ;
import java.util.function.Predicate ;
/**
* Abstract class to hold a command to be integrated into a Paper server vanilla command dispatcher.
*/
public abstract class PaperBrigadierCommand extends BrigadierCommand < BukkitBrigadierCommandSource > implements Listener {
protec ted static final Commands vanillaCommandDispatcher ;
private static final CommandDispatcher < BukkitBrigadierCommandSource > nmsDispatcher ;
static {
vanillaCommandDispatcher = ReflectWrapper . wrapTyped ( Bukkit . getServer ( ) , CraftServer . class )
. getServer ( )
. vanillaCommandDispatcher ( ) ;
nmsDispatcher = vanillaCommandDispatcher . dispatcher ( ) ;
}
priva te static final Commands vanillaCommandDispatcher ;
private static final CommandDispatcher < BukkitBrigadierCommandSource > nmsDispatcher ;
static {
vanillaCommandDispatcher = ReflectWrapper . wrapTyped ( Bukkit . getServer ( ) , CraftServer . class )
. getServer ( )
. vanillaCommandDispatcher ( ) ;
nmsDispatcher = vanillaCommandDispatcher . dispatcher ( ) ;
}
/**
* Removes a plugin command that overrides a vanilla command, so the vanilla command functionnalities are fully
* restored (so, not only the usage, but also the suggestions and the command structure sent to the client).
* @param name the name of the command to restore.
*/
public static void restoreVanillaCommand ( String name ) {
CommandMap bukkitCmdMap = Bukkit . getCommandMap ( ) ;
Command bukkitCommand = bukkitCmdMap . getCommand ( name ) ;
if ( bukkitCommand ! = null ) {
if ( VanillaCommandWrapper . REFLECT . get ( ) . isInstance ( bukkitCommand ) ) {
Log . info ( " Command / " + name + " is already a vanilla command. " ) ;
return ;
}
Log . info ( " Removing Bukkit command / " + name + " ( " + getCommandIdentity ( bukkitCommand ) + " ) " ) ;
bukkitCmdMap . getKnownCommands ( ) . remove ( name . toLowerCase ( java . util . Locale . ENGLISH ) ) ;
bukkitCommand . unregister ( bukkitCmdMap ) ;
LiteralCommandNode < BukkitBrigadierCommandSource > node = ( LiteralCommandNode < BukkitBrigadierCommandSource > ) getRootNode ( ) . getChild ( name ) ;
Command newCommand = new VanillaCommandWrapper ( vanillaCommandDispatcher , node ) . __getRuntimeInstance ( ) ;
bukkitCmdMap . getKnownCommands ( ) . put ( name . toLowerCase ( ) , newCommand ) ;
newCommand . register ( bukkitCmdMap ) ;
}
}
public static CommandDispatcher < BukkitBrigadierCommandSource > getNMSDispatcher ( ) {
return nmsD ispatcher;
}
/**
* Returns the vanilla instance of the Brigadier d ispatcher.
* @return the vanilla instance of the Brigadier dispatcher.
*/
public static CommandDispatcher < BukkitBrigadierCommandSource > getNMSDispatcher ( ) {
return nmsDispatcher ;
}
protected static RootCommandNode < BukkitBrigadierCommandSource > getRootNode ( ) {
return nmsDispatcher . getRoot ( ) ;
}
protected Plugin plugin ;
protected LiteralCommandNode < BukkitBrigadierCommandSource > commandNode ;
private Set < String > allAliases ;
public PaperBrigadierCommand ( Plugin pl ) {
plugin = pl ;
commandNode = buildCommand ( ) . build ( ) ;
postBuildCommand ( commandNode ) ;
register ( ) ;
Bukkit . getPluginManager ( ) . registerEvents ( this , plugin ) ;
}
/**
* Returns the root command node of the Brigadier dispatcher.
* @return the root command node of the Brigadier dispatcher.
*/
protected static RootCommandNode < BukkitBrigadierCommandSource > getRootNode ( ) {
return nmsDispatcher . getRoot ( ) ;
}
private void register ( ) {
String [ ] aliases = getAliases ( ) ;
if ( aliases = = null )
aliases = new String [ 0 ] ;
String pluginName = plugin . getName ( ) . toLowerCase ( ) ;
allAliases = new HashSet < > ( ) ;
registerNode ( commandNode , false ) ;
registerAlias ( pluginName + " : " + commandNode . getLiteral ( ) , true ) ;
for ( String alias : aliases ) {
registerAlias ( alias , false ) ;
registerAlias ( pluginName + " : " + alias , true ) ;
}
}
private void registerAlias ( String alias , boolean prefixed ) {
LiteralCommandNode < BukkitBrigadierCommandSource > node = literal ( alias )
. requires ( commandNode . getRequirement ( ) )
. executes ( commandNode . getCommand ( ) )
. redirect ( commandNode )
. build ( ) ;
registerNode ( node , prefixed ) ;
}
private void registerNode ( LiteralCommandNode < BukkitBrigadierCommandSource > node , boolean prefixed ) {
RootCommandNode < BukkitBrigadierCommandSource > root = getRootNode ( ) ;
String name = node . getLiteral ( ) ;
//boolean isAlias = node.getRedirect() == commandNode;
boolean forceRegistration = true ; //prefixed || !isAlias;
// nmsDispatcher integration and conflit resolution
boolean nmsRegister = false , nmsRegistered = false ;
CommandNode < BukkitBrigadierCommandSource > nmsConflited = root . getChild ( name ) ;
if ( nmsConflited ! = null ) {
if ( isFromThisCommand ( nmsConflited ) ) {
// this command is already registered in NMS
// don’ t need to register again
nmsRegistered = true ;
}
else if ( forceRegistration ) {
nmsRegister = true ;
Log . info ( " Overwriting Brigadier command / " + name ) ;
}
else {
Log . severe ( " / " + name + " already in NMS Brigadier instance. "
+ " Wont replace it because registration is not forced. " ) ;
}
}
else {
nmsRegister = true ;
}
if ( nmsRegister ) {
@SuppressWarnings ( " unchecked " )
var rCommandNode = ReflectWrapper . wrapTyped ( root , fr . pandacube . lib . paper . reflect . wrapper . brigadier . CommandNode . class ) ;
rCommandNode . removeCommand ( name ) ;
root . addChild ( node ) ;
nmsRegistered = true ;
}
if ( ! nmsRegistered ) {
return ;
}
allAliases . add ( name ) ;
// bukkit dispatcher conflict resolution
boolean bukkitRegister = false ;
CommandMap bukkitCmdMap = Bukkit . getCommandMap ( ) ;
Command bukkitConflicted = bukkitCmdMap . getCommand ( name ) ;
if ( bukkitConflicted ! = null ) {
if ( isFromThisCommand ( bukkitConflicted ) ) {
// nothing to do, already good
}
else if ( forceRegistration ) {
bukkitRegister = true ;
Log . info ( " Overwriting Bukkit command / " + name
+ " ( " + getCommandIdentity ( bukkitConflicted ) + " ) " ) ;
}
else {
Log . severe ( " / " + name + " already in Bukkit "
+ " dispatcher ( " + getCommandIdentity ( bukkitConflicted )
+ " ). Wont replace it because registration is not forced. " ) ;
}
}
else {
bukkitRegister = true ;
}
if ( bukkitRegister ) {
bukkitCmdMap . getKnownCommands ( ) . remove ( name . toLowerCase ( ) ) ;
if ( bukkitConflicted ! = null )
bukkitConflicted . unregister ( bukkitCmdMap ) ;
Command newCommand = new VanillaCommandWrapper ( vanillaCommandDispatcher , node ) . __getRuntimeInstance ( ) ;
bukkitCmdMap . getKnownCommands ( ) . put ( name . toLowerCase ( ) , newCommand ) ;
newCommand . register ( bukkitCmdMap ) ;
}
}
private boolean isFromThisCommand ( CommandNode < BukkitBrigadierCommandSource > node ) {
return node = = commandNode | | node . getRedirect ( ) = = commandNode ;
}
private boolean isFromThisCommand ( Command bukkitCmd ) {
if ( VanillaCommandWrapper . REFLECT . get ( ) . isInstance ( bukkitCmd ) ) {
return isFromThisCommand ( ReflectWrapper . wrapTyped ( ( BukkitCommand ) bukkitCmd , VanillaCommandWrapper . class ) . vanillaCommand ( ) ) ;
}
return false ;
}
protected static String getCommandIdentity ( Command bukkitCmd ) {
if ( bukkitCmd instanceof PluginCommand cmd ) {
return " Bukkit command: / " + cmd . getName ( ) + " from plugin " + cmd . getPlugin ( ) . getName ( ) ;
}
else if ( VanillaCommandWrapper . REFLECT . get ( ) . isInstance ( bukkitCmd ) ) {
return " Vanilla command: / " + bukkitCmd . getName ( ) ;
}
else
return bukkitCmd . getClass ( ) . getName ( ) + " : / " + bukkitCmd . getName ( ) ;
}
@EventHandler
public void onPlayerCommandSend ( PlayerCommandSendEvent event ) {
event . getCommands ( ) . removeAll ( allAliases . stream ( ) . map ( s - > " minecraft: " + s ) . toList ( ) ) ;
}
@EventHandler
public void onServerLoad ( ServerLoadEvent event ) {
register ( ) ;
}
/**
* The permission that should be tested instead of "minecraft.command.cmdName".
*/
protected abstract String getTargetPermission ( ) ;
private final Plugin plugin ;
/**
* The command node of this command.
*/
protected final LiteralCommandNode < BukkitBrigadierCommandSource > commandNode ;
private final RegistrationPolicy registrationPolicy ;
private Set < String > registeredAliases ;
/**
* Instanciate this command isntance.
*
* @param pl the plugin instance.
* @param regPolicy the registration policy for this command.
*/
public PaperBrigadierCommand ( Plugin pl , RegistrationPolicy regPolicy ) {
plugin = pl ;
registrationPolicy = regPolicy ;
commandNode = buildCommand ( ) . build ( ) ;
postBuildCommand ( commandNode ) ;
register ( ) ;
Bukkit . getPluginManager ( ) . registerEvents ( this , plugin ) ;
try {
PandalibPaperPermissions . addPermissionMapping ( " minecraft.command. " + commandNode . getLiteral ( ) . toLowerCase ( ) , getTargetPermission ( ) . toLowerCase ( ) ) ;
} catch ( NoClassDefFoundError ignored ) { }
}
/**
* Instanciate this command isntance with a registration policy of {@link RegistrationPolicy#ONLY_BASE_COMMAND}.
* @param pl the plugin instance.
*/
public PaperBrigadierCommand ( Plugin pl ) {
this ( pl , RegistrationPolicy . ONLY_BASE_COMMAND ) ;
}
private void register ( ) {
String [ ] aliases = getAliases ( ) ;
if ( aliases = = null )
aliases = new String [ 0 ] ;
String pluginName = plugin . getName ( ) . toLowerCase ( ) ;
registeredAliases = new HashSet < > ( ) ;
registerNode ( commandNode , false ) ;
registerAlias ( pluginName + " : " + commandNode . getLiteral ( ) , true ) ;
for ( String alias : aliases ) {
registerAlias ( alias , false ) ;
registerAlias ( pluginName + " : " + alias , true ) ;
}
}
private void registerAlias ( String alias , boolean prefixed ) {
LiteralCommandNode < BukkitBrigadierCommandSource > node = literal ( alias )
. requires ( commandNode . getRequirement ( ) )
. executes ( commandNode . getCommand ( ) )
. redirect ( commandNode )
. build ( ) ;
registerNode ( node , prefixed ) ;
}
private void registerNode ( LiteralCommandNode < BukkitBrigadierCommandSource > node , boolean prefixed ) {
RootCommandNode < BukkitBrigadierCommandSource > root = getRootNode ( ) ;
String name = node . getLiteral ( ) ;
boolean isAlias = node . getRedirect ( ) = = commandNode ;
boolean forceRegistration = switch ( registrationPolicy ) {
case NONE - > false ;
case ONLY_BASE_COMMAND - > prefixed | | ! isAlias ;
case ALL - > true ;
} ;
// nmsDispatcher integration and conflit resolution
boolean nmsRegister = false , nmsRegistered = false ;
CommandNode < BukkitBrigadierCommandSource > nmsConflited = root . getChild ( name ) ;
if ( nmsConflited ! = null ) {
if ( isFromThisCommand ( nmsConflited ) ) {
// this command is already registered in NMS. Don’ t need to register again
nmsRegistered = true ;
}
else if ( forceRegistration ) {
nmsRegister = true ;
Log . info ( " Overwriting Brigadier command / " + name ) ;
}
else {
Log . severe ( " / " + name + " already in NMS Brigadier instance. "
+ " Wont replace it because registration is not forced. " ) ;
}
}
else {
nmsRegister = true ;
}
if ( nmsRegister ) {
@SuppressWarnings ( " unchecked " )
var rCommandNode = ReflectWrapper . wrapTyped ( root , fr . pandacube . lib . paper . reflect . wrapper . brigadier . CommandNode . class ) ;
rCommandNode . removeCommand ( name ) ;
root . addChild ( node ) ;
nmsRegistered = true ;
}
if ( ! nmsRegistered ) {
return ;
}
registeredAliases . add ( name ) ;
// bukkit dispatcher conflict resolution
boolean bukkitRegister = false ;
CommandMap bukkitCmdMap = Bukkit . getCommandMap ( ) ;
Command bukkitConflicted = bukkitCmdMap . getCommand ( name ) ;
if ( bukkitConflicted ! = null ) {
if ( ! isFromThisCommand ( bukkitConflicted ) ) {
if ( forceRegistration ) {
bukkitRegister = true ;
Log . info ( " Overwriting Bukkit command / " + name
+ " ( " + getCommandIdentity ( bukkitConflicted ) + " ) " ) ;
}
else {
Log . severe ( " / " + name + " already in Bukkit "
+ " dispatcher ( " + getCommandIdentity ( bukkitConflicted )
+ " ). Wont replace it because registration is not forced. " ) ;
}
}
}
else {
bukkitRegister = true ;
}
if ( bukkitRegister ) {
bukkitCmdMap . getKnownCommands ( ) . remove ( name . toLowerCase ( ) ) ;
if ( bukkitConflicted ! = null )
bukkitConflicted . unregister ( bukkitCmdMap ) ;
Command newCommand = new VanillaCommandWrapper ( vanillaCommandDispatcher , node ) . __getRuntimeInstance ( ) ;
bukkitCmdMap . getKnownCommands ( ) . put ( name . toLowerCase ( ) , newCommand ) ;
newCommand . register ( bukkitCmdMap ) ;
}
}
private boolean isFromThisCommand ( CommandNode < BukkitBrigadierCommandSource > node ) {
return node = = commandNode | | node . getRedirect ( ) = = commandNode ;
}
private boolean isFromThisCommand ( Command bukkitCmd ) {
if ( VanillaCommandWrapper . REFLECT . get ( ) . isInstance ( bukkitCmd ) ) {
return isFromThisCommand ( ReflectWrapper . wrapTyped ( ( BukkitCommand ) bukkitCmd , VanillaCommandWrapper . class ) . vanillaCommand ( ) ) ;
}
return false ;
}
private static String getCommandIdentity ( Command bukkitCmd ) {
if ( bukkitCmd instanceof PluginCommand cmd ) {
return " Bukkit command: / " + cmd . getName ( ) + " from plugin " + cmd . getPlugin ( ) . getName ( ) ;
}
else if ( VanillaCommandWrapper . REFLECT . get ( ) . isInstance ( bukkitCmd ) ) {
return " Vanilla command: / " + bukkitCmd . getName ( ) ;
}
else
return bukkitCmd . getClass ( ) . getName ( ) + " : / " + bukkitCmd . getName ( ) ;
}
/**
* Player command sender event handler.
* @param event the event.
*/
@EventHandler
public void onPlayerCommandSend ( PlayerCommandSendEvent event ) {
event . getCommands ( ) . removeAll ( registeredAliases . stream ( ) . map ( s - > " minecraft: " + s ) . toList ( ) ) ;
}
/**
* Server load event handler.
* @param event the event.
*/
@EventHandler
public void onServerLoad ( ServerLoadEvent event ) {
register ( ) ;
}
/**
* Returns the permission that should be tested instead of "minecraft.command.cmdName". The conversion from the
* minecraft prefixed permission node to the returned node is done by the {@code pandalib-paper-permissions} if it
* is present in the classpath during runtime.
* @return the permission that should be tested instead of "minecraft.command.cmdName".
*/
protected abstract String getTargetPermission ( ) ;
@@ -263,198 +339,304 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
public boolean isConsole ( BukkitBrigadierCommandSource wrapper ) {
return isConsole ( getCommandSender ( wrapper ) ) ;
}
public boolean isPlayer ( BukkitBrigadierCommandSource wrapper ) {
return isPlayer ( getCommandSender ( wrapper ) ) ;
}
public Predicate < BukkitBrigadierCommandSource > hasPermission ( String permission ) {
return wrapper - > getCommandSender ( wrapper ) . hasPermission ( permission ) ;
}
public boolean isConsole ( CommandSender sender ) {
return sender instanceof ConsoleCommandSender ;
}
public boolean isPlayer ( CommandSender sender ) {
return sender instanceof Player ;
}
public static CommandSender getCommandSender ( CommandContext < BukkitBrigadierCommandSource > context ) {
return getCommandSender ( context . getSource ( ) ) ;
}
public static CommandSender getCommandSender ( BukkitBrigadierCommandSource wrapper ) {
return wrapper . getBukkitSender ( ) ;
}
public static BukkitBrigadierCommandSource getBrigadierCommandSource ( CommandSender sender ) {
return VanillaCommandWrapper . getListener ( sender ) ;
}
public boolean isConsole ( BukkitBrigadierCommandSource wrapper ) {
return isConsole ( getCommandSender ( wrapper ) ) ;
}
public boolean isPlayer ( BukkitBrigadierCommandSource wrapper ) {
return isPlayer ( getCommandSender ( wrapper ) ) ;
}
public Predicate < BukkitBrigadierCommandSource > hasPermission ( String permission ) {
return wrapper - > getCommandSender ( wrapper ) . hasPermission ( permission ) ;
}
public static final SuggestionsSupplier < CommandSender > TAB_WORLDS = ( s , ti , token , a ) - > SuggestionsSupplier . collectFilteredStream ( Bukkit . getWorlds ( ) . stream ( ) . map ( World : : getName ) , token ) ;
protected SuggestionProvider < BukkitBrigadierCommandSource > wrapSuggestions ( SuggestionsSupplier < CommandSender > suggestions ) {
return wrapSuggestions ( suggestions , PaperBrigadierCommand : : getCommandSender ) ;
}
protected static com . mojang . brigadier . Command < BukkitBrigadierCommandSource > wrapCommand ( com . mojang . brigadier . Command < BukkitBrigadierCommandSource > cmd ) {
return context - > {
try {
return cmd . run ( context ) ;
} catch ( CommandSyntaxException e ) {
throw e ;
} catch ( Throwable t ) {
Log . severe ( t ) ;
getCommandSender ( context ) . sendMessage ( Chat . failureText ( " Error while using the command: " + t ) ) ;
return 0 ;
}
} ;
}
/*
* Minecraft argument type
*/
public static ArgumentType < Object > argumentMinecraftEntity ( boolean singleTarget , boolean playersOnly ) {
if ( playersOnly ) {
return singleTarget ? EntityArgument . player ( ) : EntityArgument . players ( ) ;
}
else {
return singleTarget ? EntityArgument . entity ( ) : EntityArgument . entities ( ) ;
}
}
public List < Entity > tryGetMinecraftEntityArgument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
List < fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity > nmsEntityList = es . findEntities ( context . getSource ( ) ) ;
List < Entity > entityList = new ArrayList < > ( nmsEntityList . size ( ) ) ;
for ( fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity nmsEntity : nmsEntityList ) {
entityList . add ( nmsEntity . getBukkitEntity ( ) ) ;
}
return entityList ;
}
public List < Player > tryGetMinecraftEntityArgumentPlayers ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
List < ServerPlayer > nmsPlayerList = es . findPlayers ( context . getSource ( ) ) ;
List < Player > playerList = new ArrayList < > ( nmsPlayerList . size ( ) ) ;
for ( ServerPlayer nmsPlayer : nmsPlayerList ) {
playerList . add ( nmsPlayer . getBukkitEntity ( ) ) ;
}
return playerList ;
}
public Entity tryGetMinecraftEntityArgumentOneEntity ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity nmsEntity = es . findSingleEntity ( context . getSource ( ) ) ;
return nmsEntity = = null ? null : nmsEntity . getBukkitEntity ( ) ;
}
public Player tryGetMinecraftEntityArgumentOnePlayer ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
ServerPlayer nmsPlayer = es . findSinglePlayer ( context . getSource ( ) ) ;
return nmsPlayer = = null ? null : nmsPlayer . getBukkitEntity ( ) ;
}
public static ArgumentType < Object > argumentMinecraftGameProfile ( ) {
return GameProfileArgument . gameProfile ( ) ;
}
public static ArgumentType < Object > argumentMinecraftResourceLocation ( ) {
return ResourceLocationArgument . id ( ) ;
}
public NamespacedKey tryGetMinecraftResourceLocationArgument ( CommandContext < BukkitBrigadierCommandSource > context , String argument , NamespacedKey deflt ) {
return tryGetArgument ( context , argument , ResourceLocation . MAPPING . runtimeClass ( ) ,
nmsKey - > CraftNamespacedKey . fromMinecraft ( ReflectWrapper . wrap ( nmsKey , ResourceLocation . class ) ) ,
deflt ) ;
}
public static ArgumentType < Object > argumentMinecraftBlockPosition ( ) {
return BlockPosArgument . blockPos ( ) ;
}
public BlockVector tryGetMinecraftBlockPositionArgument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
Coordinates coord = ReflectWrapper . wrap ( tryGetArgument ( context , argument , Coordinates . MAPPING . runtimeClass ( ) ) , Coordinates . class ) ;
if ( coord = = null )
return null ;
BlockPos bp = coord . getBlockPos ( context . getSource ( ) ) ;
return new BlockVector ( bp . getX ( ) , bp . getY ( ) , bp . getZ ( ) ) ;
/**
* Tells if the provided command sender is the console.
* @param sender the sender to test if it’ s the console or not.
* @return true if the sender is the console, false otherwise.
*/
public boolean isConsole ( CommandSender sender ) {
return sender instanceof ConsoleCommandSender ;
}
}
public static ArgumentType < Object > argumentMinecraftVec3 ( ) {
return Vec3Argument . vec3 ( true ) ;
}
public Vector tryGetMinecraftVec3Argument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
Coordinates coord = ReflectWrapper . wrap ( tryGetArgument ( context , argument , Coordinates . MAPPING . runtimeClass ( ) ) , Coordinates . class ) ;
return coord = = null ? null : CraftVector . toBukkit ( coord . getPosition ( context . getSource ( ) ) ) ;
}
/**
* Tells if the provided command sender is a player.
* @param sender the sender to test if it’ s a player or not.
* @return true if the sender is a player, false otherwise.
*/
public boolean isPlayer ( CommandSender sender ) {
return sender instanceof Player ;
}
/**
* Gets the Bukkit command sender from the provided context.
* @param context the command context from which to get the Bukkit command sender.
* @return the Bukkit command sender.
*/
public static CommandSender getCommandSender ( CommandContext < BukkitBrigadierCommandSource > context ) {
return getCommandSender ( context . getSource ( ) ) ;
}
public static ArgumentType < Object > argumentMinecraftChatComponent ( ) {
return ComponentArgument . textComponent ( ) ;
}
public Component tryGetMinecraftChatComponentArgument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
var nmsComponent = ReflectWrapper . wrap (
tryGetArgument ( context , argument , fr . pandacube . lib . paper . reflect . wrapper . minecraft . network . chat . Component . MAPPING . runtimeClass ( ) ) ,
fr . pandacube . lib . paper . reflect . wrapper . minecraft . network . chat . Component . class
) ;
return nmsComponent = = null ? null : PaperAdventure . asAdventure ( nmsComponent ) ;
}
/**
* Gets the Bukkit command sender from the provided wrapper.
* @param wrapper the wrapper from which to get the Bukkit command sender.
* @return the Bukkit command sender.
*/
public static CommandSender getCommandSender ( BukkitBrigadierCommandSource wrapper ) {
return wrapper . getBukkitSender ( ) ;
}
/**
* Gets a new instance of a command sender wrapper for the provided command sender.
* @param sender the command sender.
* @return a new instance of a command sender wrapper for the provided command sender.
*/
public static BukkitBrigadierCommandSource getBrigadierCommandSource ( CommandSender sender ) {
return VanillaCommandWrapper . getListener ( sender ) ;
}
/**
* A suggestions supplier that suggests the names of the worlds currently loaded on this server.
*/
public static final SuggestionsSupplier < CommandSender > TAB_WORLDS = SuggestionsSupplier . fromStreamSupplier ( ( ) - > Bukkit . getWorlds ( ) . stream ( ) . map ( World : : getName ) ) ;
/**
* Wraps the provided {@link SuggestionsSupplier} into a Brigadier’ s {@link SuggestionProvider}.
* @param suggestions the suggestions to wrap.
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
*/
protected SuggestionProvider < BukkitBrigadierCommandSource > wrapSuggestions ( SuggestionsSupplier < CommandSender > suggestions ) {
return wrapSuggestions ( suggestions , PaperBrigadierCommand : : getCommandSender ) ;
}
/**
* Wraps the provided brigadier command executor in another one that logs eventual throw exceptions and informs the
* player.
* The default behaviour of the vanilla instance of the Brigadier dispatcher is to ignore any unchecked exception
* thrown by a command executor.
* @param cmd the command executor to wrap.
* @return a wrapper command executor.
*/
protected static com . mojang . brigadier . Command < BukkitBrigadierCommandSource > wrapCommand ( com . mojang . brigadier . Command < BukkitBrigadierCommandSource > cmd ) {
return context - > {
try {
return cmd . run ( context ) ;
} catch ( CommandSyntaxException e ) {
throw e ;
} catch ( Throwable t ) {
Log . severe ( t ) ;
getCommandSender ( context ) . sendMessage ( Chat . failureText ( " Error while executing the command: " + t ) ) ;
return 0 ;
}
} ;
}
/*
* Minecraft argument type
*/
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:entity}.
* @param singleTarget if this argument takes only a single target.
* @param playersOnly if this argument takes players only.
* @return the {@code minecraft:entity} argument type with the specified parameters.
*/
public static ArgumentType < Object > argumentMinecraftEntity ( boolean singleTarget , boolean playersOnly ) {
if ( playersOnly ) {
return singleTarget ? EntityArgument . player ( ) : EntityArgument . players ( ) ;
}
else {
return singleTarget ? EntityArgument . entity ( ) : EntityArgument . entities ( ) ;
}
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (list of entities), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public List < Entity > tryGetMinecraftEntityArgument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
List < fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity > nmsEntityList = es . findEntities ( context . getSource ( ) ) ;
List < Entity > entityList = new ArrayList < > ( nmsEntityList . size ( ) ) ;
for ( fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity nmsEntity : nmsEntityList ) {
entityList . add ( nmsEntity . getBukkitEntity ( ) ) ;
}
return entityList ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (list of players), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public List < Player > tryGetMinecraftEntityArgumentPlayers ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
List < ServerPlayer > nmsPlayerList = es . findPlayers ( context . getSource ( ) ) ;
List < Player > playerList = new ArrayList < > ( nmsPlayerList . size ( ) ) ;
for ( ServerPlayer nmsPlayer : nmsPlayerList ) {
playerList . add ( nmsPlayer . getBukkitEntity ( ) ) ;
}
return playerList ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (one entity), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public Entity tryGetMinecraftEntityArgumentOneEntity ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
fr . pandacube . lib . paper . reflect . wrapper . minecraft . world . Entity nmsEntity = es . findSingleEntity ( context . getSource ( ) ) ;
return nmsEntity = = null ? null : nmsEntity . getBukkitEntity ( ) ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (one player), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public Player tryGetMinecraftEntityArgumentOnePlayer ( CommandContext < BukkitBrigadierCommandSource > context , String argument ) {
EntitySelector es = ReflectWrapper . wrap ( tryGetArgument ( context , argument , EntitySelector . MAPPING . runtimeClass ( ) ) , EntitySelector . class ) ;
if ( es = = null )
return null ;
ServerPlayer nmsPlayer = es . findSinglePlayer ( context . getSource ( ) ) ;
return nmsPlayer = = null ? null : nmsPlayer . getBukkitEntity ( ) ;
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:block_pos}.
* @return the {@code minecraft:block_pos} argument type.
*/
public static ArgumentType < Object > argumentMinecraftBlockPosition ( ) {
return BlockPosArgument . blockPos ( ) ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:block_pos}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a defualt value if the argument is not found.
* @return the value of the argument.
*/
public BlockVector tryGetMinecraftBlockPositionArgument ( CommandContext < BukkitBrigadierCommandSource > context ,
String argument , BlockVector deflt ) {
return tryGetArgument ( context , argument , Coordinates . MAPPING . runtimeClass ( ) , nmsCoord - > {
BlockPos bp = ReflectWrapper . wrap ( nmsCoord , Coordinates . class ) . getBlockPos ( context . getSource ( ) ) ;
return new BlockVector ( bp . getX ( ) , bp . getY ( ) , bp . getZ ( ) ) ;
} , deflt ) ;
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:vec3}.
* @return the {@code minecraft:vec3} argument type.
*/
public static ArgumentType < Object > argumentMinecraftVec3 ( ) {
return Vec3Argument . vec3 ( true ) ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:vec3}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a defualt value if the argument is not found.
* @return the value of the argument.
*/
public Vector tryGetMinecraftVec3Argument ( CommandContext < BukkitBrigadierCommandSource > context , String argument ,
Vector deflt ) {
return tryGetArgument ( context , argument , Coordinates . MAPPING . runtimeClass ( ) ,
nmsCoord - > CraftVector . toBukkit (
ReflectWrapper . wrap ( nmsCoord , Coordinates . class ) . getPosition ( context . getSource ( ) )
) ,
deflt ) ;
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:component}.
* @return the {@code minecraft:component} argument type.
*/
public static ArgumentType < Object > argumentMinecraftChatComponent ( ) {
return ComponentArgument . textComponent ( ) ;
}
/**
* Gets the value of the provided argument of type {@code minecraft:component}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a defualt value if the argument is not found.
* @return the value of the argument.
*/
public Component tryGetMinecraftChatComponentArgument ( CommandContext < BukkitBrigadierCommandSource > context ,
String argument , Component deflt ) {
return tryGetArgument ( context , argument ,
fr . pandacube . lib . paper . reflect . wrapper . minecraft . network . chat . Component . MAPPING . runtimeClass ( ) ,
nmsComp - > PaperAdventure . asAdventure (
ReflectWrapper . wrap ( nmsComp ,
fr . pandacube . lib . paper . reflect . wrapper . minecraft . network . chat . Component . class )
) ,
deflt ) ;
}
/**
* All possible choices on how to force the registration of a command, based on certain conditions.
*/
public enum RegistrationPolicy {
/**
* Do not force to register a command node or an alias if there is already a command with that name in the
* vanilla Brigadier dispatcher.
* Note that all plugin-name-prefixed aliases will be registered anyway.
*/
NONE ,
/**
* Force only the base command (but not the aliases) to be registered, even if a command with that name already
* exists in the vanilla Brigadier dispatcher.
*/
ONLY_BASE_COMMAND ,
/**
* Force the command and all of its aliases to be registered, even if a command with the same name or alias
* already exists in the vanilla Brigadier dispatcher.
*/
ALL
}
}