2020-04-24 03:25:58 +02:00
|
|
|
package net.minestom.server.command;
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
import net.minestom.server.command.builder.Command;
|
|
|
|
import net.minestom.server.command.builder.CommandDispatcher;
|
|
|
|
import net.minestom.server.command.builder.CommandSyntax;
|
|
|
|
import net.minestom.server.command.builder.arguments.*;
|
2020-07-14 13:35:07 +02:00
|
|
|
import net.minestom.server.command.builder.arguments.minecraft.*;
|
2020-07-10 22:50:05 +02:00
|
|
|
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEnchantment;
|
|
|
|
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEntityType;
|
|
|
|
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentParticle;
|
|
|
|
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentPotion;
|
2020-07-10 16:37:18 +02:00
|
|
|
import net.minestom.server.command.builder.arguments.number.ArgumentDouble;
|
|
|
|
import net.minestom.server.command.builder.arguments.number.ArgumentFloat;
|
|
|
|
import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
|
2020-07-10 22:50:05 +02:00
|
|
|
import net.minestom.server.command.builder.arguments.number.ArgumentNumber;
|
2020-07-10 18:12:29 +02:00
|
|
|
import net.minestom.server.command.builder.condition.CommandCondition;
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.entity.Player;
|
2020-05-07 15:46:21 +02:00
|
|
|
import net.minestom.server.event.player.PlayerCommandEvent;
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
|
|
|
import net.minestom.server.utils.ArrayUtils;
|
2020-05-23 04:20:01 +02:00
|
|
|
import net.minestom.server.utils.validate.Check;
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
import java.util.*;
|
2020-07-10 22:50:05 +02:00
|
|
|
import java.util.function.Consumer;
|
2020-04-05 10:15:21 +02:00
|
|
|
|
|
|
|
public class CommandManager {
|
|
|
|
|
2020-07-01 21:03:53 +02:00
|
|
|
private boolean running;
|
2020-04-05 10:15:21 +02:00
|
|
|
private String commandPrefix = "/";
|
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
private ConsoleSender consoleSender = new ConsoleSender();
|
|
|
|
|
2020-07-14 13:35:07 +02:00
|
|
|
private CommandDispatcher dispatcher = new CommandDispatcher();
|
2020-04-05 10:15:21 +02:00
|
|
|
private Map<String, CommandProcessor> commandProcessorMap = new HashMap<>();
|
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
public CommandManager() {
|
2020-07-01 21:03:53 +02:00
|
|
|
running = true;
|
2020-06-21 14:01:03 +02:00
|
|
|
// Setup console thread
|
2020-07-01 21:03:53 +02:00
|
|
|
Thread consoleThread = new Thread(() -> {
|
2020-07-21 18:48:15 +02:00
|
|
|
final Scanner scanner = new Scanner(System.in);
|
2020-07-01 21:03:53 +02:00
|
|
|
while (running) {
|
2020-07-10 16:37:18 +02:00
|
|
|
if (scanner.hasNext()) {
|
2020-07-01 21:03:53 +02:00
|
|
|
String command = scanner.nextLine();
|
|
|
|
if (!command.startsWith(commandPrefix))
|
|
|
|
continue;
|
|
|
|
command = command.replaceFirst(commandPrefix, "");
|
|
|
|
execute(consoleSender, command);
|
|
|
|
}
|
2020-06-21 14:01:03 +02:00
|
|
|
}
|
2020-07-01 21:03:53 +02:00
|
|
|
}, "ConsoleCommand-Thread");
|
|
|
|
consoleThread.setDaemon(true);
|
|
|
|
consoleThread.start();
|
|
|
|
}
|
|
|
|
|
2020-07-23 07:36:49 +02:00
|
|
|
/**
|
|
|
|
* Stop the console responsive for the console commands processing
|
|
|
|
* <p>
|
|
|
|
* WARNING: it cannot be re-run later
|
|
|
|
*/
|
2020-07-01 21:03:53 +02:00
|
|
|
public void stopConsoleThread() {
|
|
|
|
running = false;
|
2020-06-21 14:01:03 +02:00
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Register a command with all the auto-completion features
|
|
|
|
*
|
|
|
|
* @param command the command to register
|
|
|
|
*/
|
2020-07-14 13:35:07 +02:00
|
|
|
public void register(Command command) {
|
2020-04-05 10:15:21 +02:00
|
|
|
this.dispatcher.register(command);
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Register a simple command without auto-completion
|
|
|
|
*
|
|
|
|
* @param commandProcessor the command to register
|
|
|
|
*/
|
2020-04-05 10:15:21 +02:00
|
|
|
public void register(CommandProcessor commandProcessor) {
|
|
|
|
this.commandProcessorMap.put(commandProcessor.getCommandName().toLowerCase(), commandProcessor);
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Execute a command for a sender
|
|
|
|
*
|
|
|
|
* @param sender the sender of the command
|
|
|
|
* @param command the raw command string (without the command prefix)
|
|
|
|
* @return
|
|
|
|
*/
|
2020-06-21 14:01:03 +02:00
|
|
|
public boolean execute(CommandSender sender, String command) {
|
|
|
|
Check.notNull(sender, "Source cannot be null");
|
2020-05-23 04:20:01 +02:00
|
|
|
Check.notNull(command, "Command string cannot be null");
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
if (sender instanceof Player) {
|
|
|
|
Player player = (Player) sender;
|
2020-04-29 19:23:47 +02:00
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
PlayerCommandEvent playerCommandEvent = new PlayerCommandEvent(player, command);
|
|
|
|
player.callEvent(PlayerCommandEvent.class, playerCommandEvent);
|
2020-04-29 19:23:47 +02:00
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
if (playerCommandEvent.isCancelled())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
command = playerCommandEvent.getCommand();
|
|
|
|
}
|
2020-04-29 19:23:47 +02:00
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
try {
|
2020-07-21 18:04:02 +02:00
|
|
|
// Check for rich-command
|
2020-06-21 14:01:03 +02:00
|
|
|
this.dispatcher.execute(sender, command);
|
2020-04-05 10:15:21 +02:00
|
|
|
return true;
|
|
|
|
} catch (NullPointerException e) {
|
2020-07-21 18:04:02 +02:00
|
|
|
// Check for legacy-command
|
2020-07-21 18:48:15 +02:00
|
|
|
final String[] splitted = command.split(" ");
|
|
|
|
final String commandName = splitted[0];
|
|
|
|
final CommandProcessor commandProcessor = commandProcessorMap.get(commandName.toLowerCase());
|
2020-04-05 10:15:21 +02:00
|
|
|
if (commandProcessor == null)
|
|
|
|
return false;
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
// Execute the legacy-command
|
2020-07-21 18:48:15 +02:00
|
|
|
final String[] args = command.substring(command.indexOf(" ") + 1).split(" ");
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-06-21 14:01:03 +02:00
|
|
|
return commandProcessor.process(sender, commandName, args);
|
2020-04-05 10:15:21 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Get the current command prefix (what should always be before the command name, ie: '/')
|
|
|
|
*
|
|
|
|
* @return the command prefix
|
|
|
|
*/
|
2020-04-05 10:15:21 +02:00
|
|
|
public String getCommandPrefix() {
|
|
|
|
return commandPrefix;
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Change the command prefix
|
|
|
|
* <p>
|
|
|
|
* This field can be changed half-way, but the client auto-completion still expect the '/' char
|
|
|
|
*
|
|
|
|
* @param commandPrefix the new command prefix
|
|
|
|
*/
|
2020-04-05 10:15:21 +02:00
|
|
|
public void setCommandPrefix(String commandPrefix) {
|
|
|
|
this.commandPrefix = commandPrefix;
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Get the console sender (which is used as a {@link CommandSender})
|
|
|
|
*
|
|
|
|
* @return the console sender
|
|
|
|
*/
|
2020-06-21 14:01:03 +02:00
|
|
|
public ConsoleSender getConsoleSender() {
|
|
|
|
return consoleSender;
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:04:02 +02:00
|
|
|
/**
|
|
|
|
* Get the declare commands packet for a specific player
|
|
|
|
* <p>
|
|
|
|
* Can be used to update the player auto-completion list
|
|
|
|
*
|
|
|
|
* @param player the player to get the commands packet
|
|
|
|
* @return the {@link DeclareCommandsPacket} for {@code player}
|
|
|
|
*/
|
2020-04-26 06:34:08 +02:00
|
|
|
public DeclareCommandsPacket createDeclareCommandsPacket(Player player) {
|
2020-07-10 18:12:29 +02:00
|
|
|
return buildPacket(player);
|
2020-04-05 10:15:21 +02:00
|
|
|
}
|
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
/*private DeclareCommandsPacket buildPacket(Player player) {
|
2020-04-26 06:34:08 +02:00
|
|
|
DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
|
|
|
|
|
2020-04-05 17:46:29 +02:00
|
|
|
List<String> commands = new ArrayList<>();
|
2020-06-21 14:01:03 +02:00
|
|
|
for (Command<CommandSender> command : dispatcher.getCommands()) {
|
2020-04-26 06:34:08 +02:00
|
|
|
CommandCondition<Player> commandCondition = command.getCondition();
|
|
|
|
if (commandCondition != null) {
|
|
|
|
// Do not show command if return false
|
|
|
|
if (!commandCondition.apply(player)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 17:46:29 +02:00
|
|
|
commands.add(command.getName());
|
|
|
|
for (String alias : command.getAliases()) {
|
|
|
|
commands.add(alias);
|
|
|
|
}
|
|
|
|
}
|
2020-04-26 06:34:08 +02:00
|
|
|
|
2020-04-05 17:46:29 +02:00
|
|
|
for (CommandProcessor commandProcessor : commandProcessorMap.values()) {
|
2020-04-26 06:34:08 +02:00
|
|
|
// Do not show command if return false
|
|
|
|
if (!commandProcessor.hasAccess(player))
|
|
|
|
continue;
|
|
|
|
|
2020-04-05 17:46:29 +02:00
|
|
|
commands.add(commandProcessor.getCommandName());
|
2020-04-25 23:51:45 +02:00
|
|
|
String[] aliases = commandProcessor.getAliases();
|
|
|
|
if (aliases == null || aliases.length == 0)
|
|
|
|
continue;
|
|
|
|
for (String alias : aliases) {
|
|
|
|
commands.add(alias);
|
|
|
|
}
|
2020-04-05 17:46:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
|
|
|
|
ArrayList<Integer> rootChildren = new ArrayList<>();
|
|
|
|
|
|
|
|
DeclareCommandsPacket.Node argNode = new DeclareCommandsPacket.Node();
|
|
|
|
argNode.flags = 0b10;
|
|
|
|
argNode.name = "arg";
|
|
|
|
argNode.parser = "brigadier:string";
|
|
|
|
argNode.properties = packetWriter -> {
|
|
|
|
packetWriter.writeVarInt(0);
|
|
|
|
};
|
|
|
|
int argOffset = nodes.size();
|
|
|
|
nodes.add(argNode);
|
|
|
|
argNode.children = new int[]{argOffset};
|
|
|
|
|
|
|
|
for (String commandName : commands) {
|
|
|
|
|
|
|
|
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
|
|
|
literalNode.flags = 0b1;
|
|
|
|
literalNode.name = commandName;
|
|
|
|
literalNode.children = new int[]{argOffset};
|
|
|
|
|
|
|
|
rootChildren.add(nodes.size());
|
|
|
|
nodes.add(literalNode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node();
|
|
|
|
rootNode.flags = 0;
|
|
|
|
rootNode.children = ArrayUtils.toArray(rootChildren);
|
|
|
|
|
|
|
|
nodes.add(rootNode);
|
|
|
|
|
2020-05-25 12:25:39 +02:00
|
|
|
declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[0]);
|
2020-04-05 17:46:29 +02:00
|
|
|
declareCommandsPacket.rootIndex = nodes.size() - 1;
|
2020-04-26 06:34:08 +02:00
|
|
|
|
|
|
|
return declareCommandsPacket;
|
2020-07-10 16:37:18 +02:00
|
|
|
}*/
|
2020-04-05 17:46:29 +02:00
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
private DeclareCommandsPacket buildPacket(Player player) {
|
2020-07-10 16:37:18 +02:00
|
|
|
DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
|
2020-04-05 10:15:21 +02:00
|
|
|
|
|
|
|
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
|
2020-07-10 18:12:29 +02:00
|
|
|
// Contains the children of the main node (all commands name)
|
2020-04-05 10:15:21 +02:00
|
|
|
ArrayList<Integer> rootChildren = new ArrayList<>();
|
|
|
|
|
2020-07-14 13:35:07 +02:00
|
|
|
for (Command command : dispatcher.getCommands()) {
|
2020-07-10 18:12:29 +02:00
|
|
|
// Check if player should see this command
|
2020-07-14 13:35:07 +02:00
|
|
|
CommandCondition commandCondition = command.getCondition();
|
2020-07-10 18:12:29 +02:00
|
|
|
if (commandCondition != null) {
|
|
|
|
// Do not show command if return false
|
|
|
|
if (!commandCondition.apply(player)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The main root of this command
|
2020-04-05 10:15:21 +02:00
|
|
|
ArrayList<Integer> cmdChildren = new ArrayList<>();
|
2020-07-10 18:12:29 +02:00
|
|
|
Collection<CommandSyntax> syntaxes = command.getSyntaxes();
|
|
|
|
|
|
|
|
List<String> names = new ArrayList<>();
|
|
|
|
names.add(command.getName());
|
|
|
|
for (String alias : command.getAliases()) {
|
|
|
|
names.add(alias);
|
|
|
|
}
|
|
|
|
for (String name : names) {
|
|
|
|
createCommand(nodes, cmdChildren, name, syntaxes, rootChildren);
|
|
|
|
}
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
}
|
2020-07-10 22:50:05 +02:00
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
final List<String> simpleCommands = new ArrayList<>();
|
|
|
|
for (CommandProcessor commandProcessor : commandProcessorMap.values()) {
|
|
|
|
// Do not show command if return false
|
|
|
|
if (!commandProcessor.hasAccess(player))
|
|
|
|
continue;
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
simpleCommands.add(commandProcessor.getCommandName());
|
|
|
|
String[] aliases = commandProcessor.getAliases();
|
|
|
|
if (aliases == null || aliases.length == 0)
|
|
|
|
continue;
|
|
|
|
for (String alias : aliases) {
|
|
|
|
simpleCommands.add(alias);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (String simpleCommand : simpleCommands) {
|
|
|
|
// TODO server suggestion
|
2020-04-05 10:15:21 +02:00
|
|
|
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
2020-07-10 18:12:29 +02:00
|
|
|
literalNode.flags = getFlag(NodeType.LITERAL, true, false, false);
|
|
|
|
literalNode.name = simpleCommand;
|
|
|
|
literalNode.children = new int[0];
|
|
|
|
//literalNode.suggestionsType = "minecraft:ask_server";
|
2020-04-05 10:15:21 +02:00
|
|
|
|
|
|
|
rootChildren.add(nodes.size());
|
|
|
|
nodes.add(literalNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node();
|
|
|
|
rootNode.flags = 0;
|
|
|
|
rootNode.children = ArrayUtils.toArray(rootChildren);
|
|
|
|
|
|
|
|
nodes.add(rootNode);
|
|
|
|
|
2020-05-25 12:25:39 +02:00
|
|
|
declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[0]);
|
2020-04-05 10:15:21 +02:00
|
|
|
declareCommandsPacket.rootIndex = nodes.size() - 1;
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
return declareCommandsPacket;
|
2020-04-05 10:15:21 +02:00
|
|
|
}
|
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
private void createCommand(List<DeclareCommandsPacket.Node> nodes, ArrayList<Integer> cmdChildren, String name, Collection<CommandSyntax> syntaxes, ArrayList<Integer> rootChildren) {
|
|
|
|
|
|
|
|
DeclareCommandsPacket.Node literalNode = createMainNode(name, syntaxes.isEmpty());
|
|
|
|
|
|
|
|
rootChildren.add(nodes.size());
|
|
|
|
nodes.add(literalNode);
|
|
|
|
|
|
|
|
for (CommandSyntax syntax : syntaxes) {
|
|
|
|
// Represent the last nodes computed in the last iteration
|
|
|
|
List<DeclareCommandsPacket.Node> lastNodes = null;
|
|
|
|
|
|
|
|
// Represent the children of the last node
|
|
|
|
ArrayList<Integer> argChildren = null;
|
|
|
|
|
|
|
|
final Argument[] arguments = syntax.getArguments();
|
|
|
|
for (int i = 0; i < arguments.length; i++) {
|
|
|
|
final Argument argument = arguments[i];
|
|
|
|
final boolean isFirst = i == 0;
|
|
|
|
final boolean isLast = i == arguments.length - 1;
|
|
|
|
|
|
|
|
|
|
|
|
List<DeclareCommandsPacket.Node> argumentNodes = toNodes(argument, isLast);
|
|
|
|
for (DeclareCommandsPacket.Node node : argumentNodes) {
|
|
|
|
final int childId = nodes.size();
|
|
|
|
|
|
|
|
if (isFirst) {
|
|
|
|
// Add to main command child
|
|
|
|
cmdChildren.add(childId);
|
|
|
|
} else {
|
|
|
|
// Add to previous argument children
|
|
|
|
argChildren.add(childId);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastNodes != null) {
|
2020-07-23 07:36:49 +02:00
|
|
|
final int[] children = ArrayUtils.toArray(argChildren);
|
2020-07-10 18:12:29 +02:00
|
|
|
lastNodes.forEach(n -> n.children = children);
|
|
|
|
}
|
|
|
|
|
|
|
|
nodes.add(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
//System.out.println("debug: " + argument.getId() + " : " + isFirst + " : " + isLast);
|
|
|
|
//System.out.println("debug2: " + i);
|
|
|
|
//System.out.println("size: " + (argChildren != null ? argChildren.size() : "NULL"));
|
|
|
|
|
|
|
|
if (isLast) {
|
|
|
|
// Last argument doesn't have children
|
2020-07-23 07:36:49 +02:00
|
|
|
final int[] children = new int[0];
|
2020-07-10 18:12:29 +02:00
|
|
|
argumentNodes.forEach(node -> node.children = children);
|
|
|
|
} else {
|
|
|
|
// Create children list which will be filled during next iteration
|
|
|
|
argChildren = new ArrayList<>();
|
|
|
|
lastNodes = argumentNodes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-07-23 07:36:49 +02:00
|
|
|
final int[] children = ArrayUtils.toArray(cmdChildren);
|
2020-07-10 18:12:29 +02:00
|
|
|
//System.out.println("test " + children.length + " : " + children[0]);
|
|
|
|
literalNode.children = children;
|
|
|
|
if (children.length > 0) {
|
|
|
|
literalNode.redirectedNode = children[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private DeclareCommandsPacket.Node createMainNode(String name, boolean executable) {
|
|
|
|
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
|
|
|
literalNode.flags = getFlag(NodeType.LITERAL, executable, false, false);
|
|
|
|
literalNode.name = name;
|
|
|
|
|
|
|
|
return literalNode;
|
|
|
|
}
|
|
|
|
|
2020-08-01 07:35:16 +02:00
|
|
|
private List<DeclareCommandsPacket.Node> toNodes(Argument<?> argument, boolean executable) {
|
2020-07-10 18:12:29 +02:00
|
|
|
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
|
2020-04-05 10:15:21 +02:00
|
|
|
|
2020-07-14 13:35:07 +02:00
|
|
|
/*DeclareCommandsPacket.Node testNode = simpleArgumentNode(nodes, argument, executable);
|
2020-07-11 14:16:36 +02:00
|
|
|
testNode.parser = "minecraft:entity";
|
|
|
|
testNode.properties = packetWriter -> packetWriter.writeByte((byte) 0x0);
|
2020-07-10 22:50:05 +02:00
|
|
|
|
|
|
|
if (true) {
|
|
|
|
return nodes;
|
2020-07-14 13:35:07 +02:00
|
|
|
}*/
|
2020-07-10 22:50:05 +02:00
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
if (argument instanceof ArgumentBoolean) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
argumentNode.parser = "brigadier:bool";
|
|
|
|
argumentNode.properties = packetWriter -> packetWriter.writeByte((byte) 0);
|
|
|
|
} else if (argument instanceof ArgumentDouble) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
ArgumentDouble argumentDouble = (ArgumentDouble) argument;
|
|
|
|
argumentNode.parser = "brigadier:double";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
2020-07-10 22:50:05 +02:00
|
|
|
packetWriter.writeByte(getNumberProperties(argumentDouble));
|
|
|
|
if (argumentDouble.hasMin())
|
|
|
|
packetWriter.writeDouble(argumentDouble.getMin());
|
|
|
|
if (argumentDouble.hasMax())
|
|
|
|
packetWriter.writeDouble(argumentDouble.getMax());
|
2020-04-05 10:15:21 +02:00
|
|
|
};
|
|
|
|
} else if (argument instanceof ArgumentFloat) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
ArgumentFloat argumentFloat = (ArgumentFloat) argument;
|
|
|
|
argumentNode.parser = "brigadier:float";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
2020-07-10 22:50:05 +02:00
|
|
|
packetWriter.writeByte(getNumberProperties(argumentFloat));
|
|
|
|
if (argumentFloat.hasMin())
|
|
|
|
packetWriter.writeFloat(argumentFloat.getMin());
|
|
|
|
if (argumentFloat.hasMax())
|
|
|
|
packetWriter.writeFloat(argumentFloat.getMax());
|
2020-04-05 10:15:21 +02:00
|
|
|
};
|
|
|
|
} else if (argument instanceof ArgumentInteger) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
ArgumentInteger argumentInteger = (ArgumentInteger) argument;
|
|
|
|
argumentNode.parser = "brigadier:integer";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
2020-07-10 22:50:05 +02:00
|
|
|
packetWriter.writeByte(getNumberProperties(argumentInteger));
|
|
|
|
if (argumentInteger.hasMin())
|
|
|
|
packetWriter.writeInt(argumentInteger.getMin());
|
|
|
|
if (argumentInteger.hasMax())
|
|
|
|
packetWriter.writeInt(argumentInteger.getMax());
|
2020-04-05 10:15:21 +02:00
|
|
|
};
|
|
|
|
} else if (argument instanceof ArgumentWord) {
|
2020-07-10 18:12:29 +02:00
|
|
|
|
|
|
|
ArgumentWord argumentWord = (ArgumentWord) argument;
|
|
|
|
|
2020-07-10 22:50:05 +02:00
|
|
|
// Add the single word properties + parser
|
|
|
|
final Consumer<DeclareCommandsPacket.Node> wordConsumer = node -> {
|
|
|
|
node.parser = "brigadier:string";
|
|
|
|
node.properties = packetWriter -> {
|
|
|
|
packetWriter.writeVarInt(0); // Single word
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
final boolean hasRestriction = argumentWord.hasRestrictions();
|
|
|
|
if (hasRestriction) {
|
2020-07-10 22:50:05 +02:00
|
|
|
// Create a node for each restrictions as literal
|
2020-07-10 18:12:29 +02:00
|
|
|
for (String restrictionWord : argumentWord.getRestrictions()) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
|
|
|
nodes.add(argumentNode);
|
|
|
|
|
|
|
|
argumentNode.flags = getFlag(NodeType.LITERAL, executable, false, false);
|
|
|
|
argumentNode.name = restrictionWord;
|
2020-07-10 22:50:05 +02:00
|
|
|
wordConsumer.accept(argumentNode);
|
2020-07-10 18:12:29 +02:00
|
|
|
}
|
|
|
|
} else {
|
2020-07-10 22:50:05 +02:00
|
|
|
// Can be any word, add only one argument node
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
2020-07-10 22:50:05 +02:00
|
|
|
wordConsumer.accept(argumentNode);
|
2020-07-10 18:12:29 +02:00
|
|
|
}
|
2020-04-05 10:15:21 +02:00
|
|
|
} else if (argument instanceof ArgumentString) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
argumentNode.parser = "brigadier:string";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
|
|
|
packetWriter.writeVarInt(1); // Quotable phrase
|
|
|
|
};
|
|
|
|
} else if (argument instanceof ArgumentStringArray) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
argumentNode.parser = "brigadier:string";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
|
|
|
packetWriter.writeVarInt(2); // Greedy phrase
|
|
|
|
};
|
2020-07-10 22:50:05 +02:00
|
|
|
} else if (argument instanceof ArgumentColor) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:color";
|
|
|
|
} else if (argument instanceof ArgumentTime) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:time";
|
|
|
|
} else if (argument instanceof ArgumentEnchantment) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:item_enchantment";
|
|
|
|
} else if (argument instanceof ArgumentParticle) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:particle";
|
|
|
|
} else if (argument instanceof ArgumentPotion) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:mob_effect";
|
|
|
|
} else if (argument instanceof ArgumentEntityType) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:entity_summon";
|
2020-07-10 23:51:38 +02:00
|
|
|
} else if (argument instanceof ArgumentIntRange) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:int_range";
|
|
|
|
} else if (argument instanceof ArgumentFloatRange) {
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:float_range";
|
2020-07-14 13:35:07 +02:00
|
|
|
} else if (argument instanceof ArgumentEntities) {
|
|
|
|
ArgumentEntities argumentEntities = (ArgumentEntities) argument;
|
|
|
|
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
|
|
|
|
argumentNode.parser = "minecraft:entity";
|
|
|
|
argumentNode.properties = packetWriter -> {
|
|
|
|
byte mask = 0;
|
|
|
|
if (argumentEntities.isOnlySingleEntity()) {
|
|
|
|
mask += 1;
|
|
|
|
}
|
|
|
|
if (argumentEntities.isOnlyPlayers()) {
|
|
|
|
mask += 2;
|
|
|
|
}
|
|
|
|
packetWriter.writeByte(mask);
|
|
|
|
};
|
2020-04-05 10:15:21 +02:00
|
|
|
}
|
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
2020-08-01 07:35:16 +02:00
|
|
|
private byte getNumberProperties(ArgumentNumber<? extends Number> argumentNumber) {
|
2020-07-10 22:50:05 +02:00
|
|
|
byte result = 0;
|
|
|
|
if (argumentNumber.hasMin())
|
|
|
|
result += 1;
|
|
|
|
if (argumentNumber.hasMax())
|
|
|
|
result += 2;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-10 18:12:29 +02:00
|
|
|
private DeclareCommandsPacket.Node simpleArgumentNode(List<DeclareCommandsPacket.Node> nodes,
|
2020-08-01 07:35:16 +02:00
|
|
|
Argument<?> argument, boolean executable) {
|
2020-07-10 18:12:29 +02:00
|
|
|
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
|
|
|
nodes.add(argumentNode);
|
|
|
|
|
|
|
|
argumentNode.flags = getFlag(NodeType.ARGUMENT, executable, false, false);
|
|
|
|
argumentNode.name = argument.getId();
|
|
|
|
|
2020-04-05 10:15:21 +02:00
|
|
|
return argumentNode;
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private byte getFlag(NodeType type, boolean executable, boolean redirect, boolean suggestionType) {
|
|
|
|
byte result = (byte) type.mask;
|
|
|
|
|
|
|
|
if (executable) {
|
|
|
|
result |= 0x4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (redirect) {
|
|
|
|
result |= 0x8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (suggestionType) {
|
2020-07-10 18:12:29 +02:00
|
|
|
result |= 0x10;
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private enum NodeType {
|
|
|
|
ROOT(0), LITERAL(0b1), ARGUMENT(0b10), NONE(0x11);
|
|
|
|
|
|
|
|
private int mask;
|
|
|
|
|
|
|
|
NodeType(int mask) {
|
|
|
|
this.mask = mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-04-05 10:15:21 +02:00
|
|
|
}
|