mirror of
https://github.com/aikar/commands.git
synced 2026-05-31 06:11:55 +00:00
Co-authored-by: Aikar <aikar@aikar.co>
This commit is contained in:
Generated
+10
-7
@@ -7,20 +7,22 @@
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="acf-sponge" />
|
||||
<module name="acf" />
|
||||
<module name="acf-example" />
|
||||
<module name="example-plugin" />
|
||||
<module name="acf-brigadier" />
|
||||
<module name="acf-paper" />
|
||||
<module name="acf-jda" />
|
||||
<module name="acf-core" />
|
||||
<module name="acf-velocity" />
|
||||
<module name="acf-bukkit" />
|
||||
<module name="acf-bungee" />
|
||||
<module name="acf-core" />
|
||||
<module name="acf-example" />
|
||||
<module name="acf-jda" />
|
||||
<module name="acf-paper" />
|
||||
<module name="acf-sponge" />
|
||||
<module name="acf-velocity" />
|
||||
<module name="example-plugin" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel>
|
||||
<module name="acf" target="1.8" />
|
||||
<module name="acf-brigadier" target="1.8" />
|
||||
<module name="acf-bukkit" target="1.8" />
|
||||
<module name="acf-bungee" target="1.8" />
|
||||
<module name="acf-core" target="1.8" />
|
||||
@@ -36,6 +38,7 @@
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="acf-brigadier" options="-parameters" />
|
||||
<module name="acf-bukkit" options="-parameters" />
|
||||
<module name="acf-bungee" options="-parameters" />
|
||||
<module name="acf-core" options="-parameters" />
|
||||
|
||||
Generated
+2
@@ -2,6 +2,8 @@
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/brigadier" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/brigadier/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/bukkit" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/bukkit/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/bungee" charset="UTF-8" />
|
||||
|
||||
+1
@@ -35,6 +35,7 @@
|
||||
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
|
||||
<option name="myAdditionalJavadocTags" value="" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="MissingJSR305" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||
<inspection_tool class="SameParameterValue" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining
|
||||
~ a copy of this software and associated documentation files (the
|
||||
~ "Software"), to deal in the Software without restriction, including
|
||||
~ without limitation the rights to use, copy, modify, merge, publish,
|
||||
~ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
~ permit persons to whom the Software is furnished to do so, subject to
|
||||
~ the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be
|
||||
~ included in all copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
~ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
~ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
~ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
~ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
~ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>co.aikar</groupId>
|
||||
<artifactId>acf-parent</artifactId>
|
||||
<version><!--VERSION-->0.5.0-SNAPSHOT<!--VERSION--></version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>acf-brigadier</artifactId>
|
||||
<version><!--VERSION-->0.5.0-SNAPSHOT<!--VERSION--></version>
|
||||
|
||||
<name>ACF (Brigadier)</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mojang-repo</id>
|
||||
<url>https://libraries.minecraft.net/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>co.aikar</groupId>
|
||||
<artifactId>acf-core</artifactId>
|
||||
<version><!--VERSION-->0.5.0-SNAPSHOT<!--VERSION--></version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>brigadier</artifactId>
|
||||
<version>1.0.17</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,164 @@
|
||||
package co.aikar.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Handles registering of commands into brigadier
|
||||
*
|
||||
* @param <S>
|
||||
* @author MiniDigger
|
||||
* @deprecated Unstable API
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableAPI
|
||||
public class ACFBrigadierManager<S> {
|
||||
|
||||
protected final CommandManager<?, ?, ?, ?, ?, ?> manager;
|
||||
|
||||
private final Map<Class<?>, ArgumentType<?>> arguments = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs a new brigadier manager, utilizing the currently active command manager
|
||||
*
|
||||
* @param manager
|
||||
*/
|
||||
ACFBrigadierManager(CommandManager<?, ?, ?, ?, ?, ?> manager) {
|
||||
manager.verifyUnstableAPI("brigadier");
|
||||
|
||||
this.manager = manager;
|
||||
|
||||
// TODO support stuff like min max via brigadier?
|
||||
registerArgument(String.class, StringArgumentType.word());
|
||||
registerArgument(float.class, FloatArgumentType.floatArg());
|
||||
registerArgument(Float.class, FloatArgumentType.floatArg());
|
||||
registerArgument(double.class, DoubleArgumentType.doubleArg());
|
||||
registerArgument(Double.class, DoubleArgumentType.doubleArg());
|
||||
registerArgument(boolean.class, BoolArgumentType.bool());
|
||||
registerArgument(Boolean.class, BoolArgumentType.bool());
|
||||
registerArgument(int.class, IntegerArgumentType.integer());
|
||||
registerArgument(Integer.class, IntegerArgumentType.integer());
|
||||
// We use integer for long due to Bungee bug, plus should really be considered same on client
|
||||
registerArgument(long.class, IntegerArgumentType.integer());
|
||||
registerArgument(Long.class, IntegerArgumentType.integer());
|
||||
}
|
||||
|
||||
<T> void registerArgument(Class<T> clazz, ArgumentType<?> type) {
|
||||
arguments.put(clazz, type);
|
||||
}
|
||||
|
||||
ArgumentType<Object> getArgumentTypeByClazz(CommandParameter param) {
|
||||
if (param.consumesRest) {
|
||||
//noinspection unchecked
|
||||
return (ArgumentType<Object>) (ArgumentType<?>) StringArgumentType.greedyString();
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (ArgumentType<Object>) arguments.getOrDefault(param.getType(), StringArgumentType.string());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given RootCommand into the given brigadir command node, utilizing the provided suggestion provider, executor and permission predicate.<br>
|
||||
* <p>
|
||||
* It recreates the root command node!
|
||||
*/
|
||||
LiteralCommandNode<S> register(RootCommand rootCommand,
|
||||
LiteralCommandNode<S> root,
|
||||
SuggestionProvider<S> suggestionProvider,
|
||||
Command<S> executor,
|
||||
BiPredicate<RootCommand, S> permCheckerRoot,
|
||||
BiPredicate<RegisteredCommand, S> permCheckerSub) {
|
||||
// recreate root to get rid of bukkits default arg
|
||||
LiteralArgumentBuilder<S> rootBuilder = LiteralArgumentBuilder.<S>literal(root.getLiteral())
|
||||
.requires(sender -> permCheckerRoot.test(rootCommand, sender));
|
||||
|
||||
root = rootBuilder.build();
|
||||
boolean isForwardingCommand = rootCommand.getDefCommand() instanceof ForwardingCommand;
|
||||
|
||||
for (Map.Entry<String, RegisteredCommand> subCommand : rootCommand.getSubCommands().entries()) {
|
||||
if ((BaseCommand.isSpecialSubcommand(subCommand.getKey()) && !isForwardingCommand) || (!subCommand.getKey().equals("help") && subCommand.getValue().prefSubCommand.equals("help"))) {
|
||||
// don't register stuff like __catchunknown and don't help command aliases
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle sub sub commands
|
||||
String commandName = subCommand.getKey();
|
||||
CommandNode<S> currentParent = root;
|
||||
CommandNode<S> subCommandNode;
|
||||
Predicate<S> subPermChecker = sender -> permCheckerSub.test(subCommand.getValue(), sender);
|
||||
if (!isForwardingCommand) {
|
||||
if (commandName.contains(" ")) {
|
||||
String[] split = ACFPatterns.SPACE.split(commandName);
|
||||
for (int i = 0; i < split.length - 1; i++) {
|
||||
if (currentParent.getChild(split[i]) == null) {
|
||||
LiteralCommandNode<S> sub = LiteralArgumentBuilder.<S>literal(split[i])
|
||||
.requires(subPermChecker).build();
|
||||
currentParent.addChild(sub);
|
||||
currentParent = sub;
|
||||
} else {
|
||||
currentParent = currentParent.getChild(split[i]);
|
||||
}
|
||||
}
|
||||
commandName = split[split.length - 1];
|
||||
}
|
||||
|
||||
subCommandNode = currentParent.getChild(commandName);
|
||||
if (subCommandNode == null) {
|
||||
LiteralArgumentBuilder<S> argumentBuilder = LiteralArgumentBuilder.<S>literal(commandName)
|
||||
.requires(subPermChecker);
|
||||
|
||||
// if we have no params, this command is actually executable
|
||||
if (subCommand.getValue().consumeInputResolvers == 0) {
|
||||
argumentBuilder.executes(executor);
|
||||
}
|
||||
subCommandNode = argumentBuilder.build();
|
||||
}
|
||||
} else {
|
||||
subCommandNode = root;
|
||||
}
|
||||
|
||||
CommandNode<S> paramNode = subCommandNode;
|
||||
CommandParameter[] parameters = subCommand.getValue().parameters;
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
CommandParameter param = parameters[i];
|
||||
CommandParameter nextParam = param.getNextParam();
|
||||
if (param.isCommandIssuer() || (param.canExecuteWithoutInput() && nextParam != null && !nextParam.canExecuteWithoutInput())) {
|
||||
continue;
|
||||
}
|
||||
RequiredArgumentBuilder<S, Object> builder = RequiredArgumentBuilder
|
||||
.<S, Object>argument(param.getName(), getArgumentTypeByClazz(param))
|
||||
.suggests(suggestionProvider)
|
||||
.requires(sender -> permCheckerSub.test(subCommand.getValue(), sender));
|
||||
|
||||
if (nextParam != null && nextParam.canExecuteWithoutInput()) {
|
||||
builder.executes(executor);
|
||||
}
|
||||
|
||||
CommandNode<S> subSubCommand = builder.build();
|
||||
paramNode.addChild(subSubCommand);
|
||||
paramNode = subSubCommand;
|
||||
}
|
||||
|
||||
if (!isForwardingCommand) {
|
||||
currentParent.addChild(subCommandNode);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -662,7 +662,7 @@ public abstract class BaseCommand {
|
||||
String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(Locale.ENGLISH);
|
||||
for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) {
|
||||
final String key = entry.getKey();
|
||||
if (key.startsWith(argString) && !CATCHUNKNOWN.equals(key) && !DEFAULT.equals(key)) {
|
||||
if (key.startsWith(argString) && !isSpecialSubcommand(key)) {
|
||||
final RegisteredCommand value = entry.getValue();
|
||||
if (!value.hasPermission(issuer) || value.isPrivate) {
|
||||
continue;
|
||||
@@ -675,6 +675,10 @@ public abstract class BaseCommand {
|
||||
return new ArrayList<>(cmds);
|
||||
}
|
||||
|
||||
static boolean isSpecialSubcommand(String key) {
|
||||
return CATCHUNKNOWN.equals(key) || DEFAULT.equals(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete a command properly per issuer and input.
|
||||
*
|
||||
@@ -839,4 +843,8 @@ public abstract class BaseCommand {
|
||||
registeredCommands.addAll(this.subCommands.values());
|
||||
return registeredCommands;
|
||||
}
|
||||
|
||||
protected SetMultimap<String, RegisteredCommand> getSubCommands() {
|
||||
return subCommands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,9 +66,13 @@ public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends
|
||||
private boolean canConsumeInput;
|
||||
private boolean optionalResolver;
|
||||
boolean consumesRest;
|
||||
private boolean isLast;
|
||||
private boolean isOptionalInput;
|
||||
private CommandParameter<CEC> nextParam;
|
||||
|
||||
public CommandParameter(RegisteredCommand<CEC> command, Parameter param, int paramIndex, boolean isLast) {
|
||||
this.parameter = param;
|
||||
this.isLast = isLast;
|
||||
this.type = param.getType();
|
||||
this.name = param.getName(); // do we care for an annotation to supply name?
|
||||
this.manager = command.manager;
|
||||
@@ -99,10 +103,12 @@ public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends
|
||||
this.values = annotations.getAnnotationValues(param, Values.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
|
||||
|
||||
this.syntax = null;
|
||||
this.isOptionalInput = !requiresInput && canConsumeInput;
|
||||
|
||||
if (!commandIssuer) {
|
||||
this.syntax = annotations.getAnnotationValue(param, Syntax.class);
|
||||
if (syntax == null) {
|
||||
if (!requiresInput && canConsumeInput) {
|
||||
if (isOptionalInput) {
|
||||
this.syntax = "[" + name + "]";
|
||||
} else if (requiresInput) {
|
||||
this.syntax = "<" + name + ">";
|
||||
@@ -184,6 +190,10 @@ public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public boolean isOptionalInput() {
|
||||
return isOptionalInput;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
@@ -275,4 +285,20 @@ public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends
|
||||
public Set<String> getRequiredPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setNextParam(CommandParameter<CEC> nextParam) {
|
||||
this.nextParam = nextParam;
|
||||
}
|
||||
|
||||
public CommandParameter<CEC> getNextParam() {
|
||||
return nextParam;
|
||||
}
|
||||
|
||||
public boolean canExecuteWithoutInput() {
|
||||
return (!canConsumeInput || isOptionalInput()) && (nextParam == null || nextParam.canExecuteWithoutInput());
|
||||
}
|
||||
|
||||
public boolean isLast() {
|
||||
return isLast;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
package co.aikar.commands;
|
||||
|
||||
import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -84,7 +84,7 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
|
||||
this.manager = this.scope.manager;
|
||||
final Annotations annotations = this.manager.getAnnotations();
|
||||
|
||||
if (BaseCommand.CATCHUNKNOWN.equals(prefSubCommand) || BaseCommand.DEFAULT.equals(prefSubCommand)) {
|
||||
if (BaseCommand.isSpecialSubcommand(prefSubCommand)) {
|
||||
prefSubCommand = "";
|
||||
command = command.trim();
|
||||
}
|
||||
@@ -110,8 +110,13 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
|
||||
int optionalResolvers = 0;
|
||||
StringBuilder syntaxBuilder = new StringBuilder(64);
|
||||
|
||||
CommandParameter<CEC> previousParam = null;
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i, i == parameters.length - 1);
|
||||
if (previousParam != null) {
|
||||
previousParam.setNextParam(parameter);
|
||||
}
|
||||
previousParam = parameter;
|
||||
if (!parameter.isCommandIssuer()) {
|
||||
if (!parameter.requiresInput()) {
|
||||
optionalResolvers++;
|
||||
@@ -247,9 +252,9 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
|
||||
} else if (allowOptional && parameter.isOptional()) {
|
||||
Object value;
|
||||
if (!parameter.isOptionalResolver() || !this.manager.hasPermission(sender, parameterPermissions)) {
|
||||
value = null;
|
||||
value = null;
|
||||
} else {
|
||||
value = resolver.getContext(context);
|
||||
value = resolver.getContext(context);
|
||||
}
|
||||
|
||||
if (value == null && parameter.getClass().isPrimitive()) {
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@
|
||||
<dependency>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.13.2-R0.1-SNAPSHOT</version>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
|
||||
package co.aikar.acfexample;
|
||||
|
||||
import co.aikar.commands.PaperCommandManager;
|
||||
import co.aikar.commands.ConditionFailedException;
|
||||
import co.aikar.commands.MessageKeys;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.PaperBrigadierManager;
|
||||
import co.aikar.commands.PaperCommandManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -46,6 +47,9 @@ public final class ACFExample extends JavaPlugin {
|
||||
// 1: Create Command Manager for your respective platform
|
||||
commandManager = new PaperCommandManager(this);
|
||||
|
||||
// enable brigadier integration for paper servers
|
||||
commandManager.enableUnstableAPI("brigadier");
|
||||
|
||||
// optional: enable unstable api to use help
|
||||
commandManager.enableUnstableAPI("help");
|
||||
|
||||
@@ -109,6 +113,12 @@ public final class ACFExample extends JavaPlugin {
|
||||
getLogger().warning("Error occurred while executing command " + command.getName());
|
||||
return false; // mark as unhandeled, sender will see default message
|
||||
});
|
||||
|
||||
// test command for brigadier
|
||||
commandManager.getCommandCompletions().registerAsyncCompletion("someobject", c ->
|
||||
Arrays.asList("1", "2", "3", "4", "5")
|
||||
);
|
||||
commandManager.registerCommand(new BrigadierTest());
|
||||
}
|
||||
|
||||
// Typical Bukkit Plugin Scaffolding
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package co.aikar.acfexample;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.CommandHelp;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Default;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.HelpCommand;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandAlias("brigadiertest")
|
||||
public class BrigadierTest extends BaseCommand {
|
||||
|
||||
@Subcommand("hello")
|
||||
@Syntax("<player>")
|
||||
@CommandCompletion("@players")
|
||||
@Description("Says hello to a player")
|
||||
public static void onHello(Player player, @Flags("other") Player arg) {
|
||||
player.sendMessage("You said hello to " + arg.getDisplayName());
|
||||
}
|
||||
|
||||
@Default
|
||||
@HelpCommand
|
||||
public static void onHelp(CommandSender sender, CommandHelp help) {
|
||||
help.showHelp();
|
||||
}
|
||||
|
||||
@Subcommand("test|test2")
|
||||
@Description("Says hello to a player")
|
||||
@CommandCompletion("true|false @range:20 @range:1-5 @range:20-30 test|test2|foo|bar true|false")
|
||||
public static void onTest(CommandSender sender, boolean booleanParam, float floatParam, double doubleParam, int integerParam, String stringParam, @Optional Boolean test2) {
|
||||
sender.sendMessage("You said: " + booleanParam + " - " + floatParam + " - " + doubleParam + " - " + integerParam + " - " + stringParam + " - " + test2 + "!");
|
||||
}
|
||||
|
||||
@Subcommand("custom")
|
||||
@Description("Try custom completions")
|
||||
@Syntax("<syntaxTest>")
|
||||
@CommandCompletion("@someobject")
|
||||
public static void onCustom(Player player, SomeObject object) {
|
||||
player.sendMessage("You said: " + object);
|
||||
}
|
||||
|
||||
@Subcommand("dummy admin")
|
||||
@CommandPermission("dummy")
|
||||
public static void onPerm(Player player) {
|
||||
player.sendMessage("You shall pass");
|
||||
}
|
||||
|
||||
@Subcommand("sub3")
|
||||
public static void sub3(Player player, String wooo) {
|
||||
player.sendMessage("Wooo " + wooo);
|
||||
}
|
||||
|
||||
@Subcommand("sub sub")
|
||||
public static void onSubSub(Player player, String wooo) {
|
||||
player.sendMessage("Wooo " + wooo);
|
||||
}
|
||||
|
||||
@Subcommand("sub2")
|
||||
public static void onSub2(Player player) {
|
||||
player.sendMessage("Sub2");
|
||||
}
|
||||
|
||||
@Subcommand("sub2 sub")
|
||||
public static void onSub2Sub(Player player, String test) {
|
||||
player.sendMessage("Sub2 sub " + test);
|
||||
}
|
||||
|
||||
@Subcommand("find|where")
|
||||
@CommandPermission("hyperverse.find")
|
||||
@CommandAlias("hvf|hvfind")
|
||||
@CommandCompletion("@players")
|
||||
public void findPlayer(final CommandSender sender, final String player) { /* stub */ }
|
||||
|
||||
@Subcommand("greedy")
|
||||
public void onGreedy(Player player, String greedyString) {
|
||||
player.sendMessage(greedyString);
|
||||
}
|
||||
|
||||
@Subcommand("notgreedy")
|
||||
public void notGreedy(Player player, @Single String notGreedy) {
|
||||
player.sendMessage(notGreedy);
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -46,10 +46,28 @@
|
||||
<version><!--VERSION-->0.5.0-SNAPSHOT<!--VERSION--></version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>co.aikar</groupId>
|
||||
<artifactId>acf-brigadier</artifactId>
|
||||
<version><!--VERSION-->0.5.0-SNAPSHOT<!--VERSION--></version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-mojangapi</artifactId>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-mojangapi</artifactId>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -51,6 +51,10 @@ class PaperAsyncTabCompleteHandler implements Listener {
|
||||
if (false) throw new CommandCompletions.SyncCompletionRequired(); // fake compiler due to SneakyThrows
|
||||
List<String> completions = getCompletions(buffer, event.getCompletions(), event.getSender(), true);
|
||||
if (completions != null) {
|
||||
// if we have no completion data, client will display an error, lets just send a space instead (https://bugs.mojang.com/browse/MC-165562)
|
||||
if (completions.size() == 1 && completions.get(0).equals("")) {
|
||||
completions.set(0, " ");
|
||||
}
|
||||
event.setCompletions(completions);
|
||||
event.setHandled(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Daniel Ennis (Aikar) - MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package co.aikar.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles registering of commands into brigadier
|
||||
*
|
||||
* @author MiniDigger
|
||||
* @deprecated Unstable API
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableAPI
|
||||
public class PaperBrigadierManager implements Listener {
|
||||
|
||||
private final PaperCommandManager manager;
|
||||
private final ACFBrigadierManager<BukkitBrigadierCommandSource> brigadierManager;
|
||||
|
||||
public PaperBrigadierManager(Plugin plugin, PaperCommandManager manager) {
|
||||
manager.verifyUnstableAPI("brigadier");
|
||||
manager.log(LogLevel.INFO, "Enabled Brigadier Support!");
|
||||
|
||||
this.manager = manager;
|
||||
this.brigadierManager = new ACFBrigadierManager<>(manager);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCommandRegister(CommandRegisteredEvent<BukkitBrigadierCommandSource> event) {
|
||||
RootCommand acfCommand = manager.getRootCommand(event.getCommandLabel());
|
||||
if (acfCommand != null) {
|
||||
event.setLiteral(brigadierManager.register(
|
||||
acfCommand,
|
||||
event.getLiteral(),
|
||||
event.getBrigadierCommand(),
|
||||
event.getBrigadierCommand(),
|
||||
this::checkPermRoot,
|
||||
this::checkPermSub
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPermSub(RegisteredCommand registeredCommand, BukkitBrigadierCommandSource sender) {
|
||||
return registeredCommand.hasPermission(manager.getCommandIssuer(sender.getBukkitSender()));
|
||||
}
|
||||
|
||||
private boolean checkPermRoot(RootCommand rootCommand, BukkitBrigadierCommandSource sender) {
|
||||
return rootCommand.hasAnyPermission(manager.getCommandIssuer(sender.getBukkitSender()));
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ import org.bukkit.plugin.Plugin;
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class PaperCommandManager extends BukkitCommandManager {
|
||||
|
||||
private boolean brigadierAvailable;
|
||||
|
||||
// If we get anything Paper specific
|
||||
public PaperCommandManager(Plugin plugin) {
|
||||
super(plugin);
|
||||
@@ -37,6 +39,21 @@ public class PaperCommandManager extends BukkitCommandManager {
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
// Ignored
|
||||
}
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent");
|
||||
brigadierAvailable = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableUnstableAPI(String api) {
|
||||
super.enableUnstableAPI(api);
|
||||
|
||||
if ("brigadier".equals(api) && brigadierAvailable) {
|
||||
new PaperBrigadierManager(plugin, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user