package net.minestom.server.command; import fr.themode.command.Command; import fr.themode.command.CommandDispatcher; import fr.themode.command.CommandSyntax; import fr.themode.command.arguments.*; import fr.themode.command.arguments.number.ArgumentDouble; import fr.themode.command.arguments.number.ArgumentFloat; import fr.themode.command.arguments.number.ArgumentInteger; import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.play.DeclareCommandsPacket; import net.minestom.server.utils.ArrayUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CommandManager { private String commandPrefix = "/"; private CommandDispatcher dispatcher = new CommandDispatcher<>(); private Map commandProcessorMap = new HashMap<>(); private DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket(); public void register(Command command) { this.dispatcher.register(command); refreshPacket(); } public void register(CommandProcessor commandProcessor) { this.commandProcessorMap.put(commandProcessor.getCommandName().toLowerCase(), commandProcessor); refreshPacket(); } public boolean execute(Player source, String command) { if (source == null) throw new NullPointerException("Source cannot be null"); if (command == null) throw new NullPointerException("Command string cannot be null"); try { this.dispatcher.execute(source, command); return true; } catch (NullPointerException e) { String[] splitted = command.split(" "); String commandName = splitted[0]; CommandProcessor commandProcessor = commandProcessorMap.get(commandName.toLowerCase()); if (commandProcessor == null) return false; String[] args = command.substring(command.indexOf(" ") + 1).split(" "); return commandProcessor.process(source, commandName, args); } } public String getCommandPrefix() { return commandPrefix; } public void setCommandPrefix(String commandPrefix) { this.commandPrefix = commandPrefix; } public DeclareCommandsPacket getDeclareCommandsPacket() { return declareCommandsPacket; } private void refreshPacket() { List commands = new ArrayList<>(); for (Command command : dispatcher.getCommands()) { commands.add(command.getName()); for (String alias : command.getAliases()) { commands.add(alias); } } for (CommandProcessor commandProcessor : commandProcessorMap.values()) { commands.add(commandProcessor.getCommandName()); } List nodes = new ArrayList<>(); ArrayList 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); declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[nodes.size()]); declareCommandsPacket.rootIndex = nodes.size() - 1; } private void refreshPacket2() { List nodes = new ArrayList<>(); ArrayList rootChildren = new ArrayList<>(); for (Command command : dispatcher.getCommands()) { ArrayList cmdChildren = new ArrayList<>(); String name = command.getName(); DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node(); literalNode.flags = 0b1; literalNode.name = name; rootChildren.add(nodes.size()); nodes.add(literalNode); for (CommandSyntax syntax : command.getSyntaxes()) { ArrayList argChildren = cmdChildren; for (Argument argument : syntax.getArguments()) { DeclareCommandsPacket.Node argumentNode = toNode(argument); argChildren.add(nodes.size()); nodes.add(argumentNode); System.out.println("size: " + argChildren.size()); argumentNode.children = ArrayUtils.toArray(argChildren); argChildren = new ArrayList<>(); } } System.out.println("test " + cmdChildren.size() + " : " + cmdChildren.get(0)); literalNode.children = ArrayUtils.toArray(cmdChildren); } DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node(); rootNode.flags = 0; rootNode.children = ArrayUtils.toArray(rootChildren); nodes.add(rootNode); declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[nodes.size()]); declareCommandsPacket.rootIndex = nodes.size() - 1; } private DeclareCommandsPacket.Node toNode(Argument argument) { DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node(); argumentNode.flags = 0b1010; argumentNode.name = argument.getId(); if (argument instanceof ArgumentBoolean) { argumentNode.parser = "brigadier:bool"; argumentNode.properties = packetWriter -> packetWriter.writeByte((byte) 0); } else if (argument instanceof ArgumentDouble) { ArgumentDouble argumentDouble = (ArgumentDouble) argument; argumentNode.parser = "brigadier:double"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); packetWriter.writeDouble(argumentDouble.min); packetWriter.writeDouble(argumentDouble.max); }; } else if (argument instanceof ArgumentFloat) { ArgumentFloat argumentFloat = (ArgumentFloat) argument; argumentNode.parser = "brigadier:float"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); packetWriter.writeFloat(argumentFloat.min); packetWriter.writeFloat(argumentFloat.max); }; } else if (argument instanceof ArgumentInteger) { ArgumentInteger argumentInteger = (ArgumentInteger) argument; argumentNode.parser = "brigadier:integer"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); packetWriter.writeInt(argumentInteger.min); packetWriter.writeInt(argumentInteger.max); }; } else if (argument instanceof ArgumentWord) { argumentNode.parser = "brigadier:string"; argumentNode.properties = packetWriter -> { packetWriter.writeVarInt(0); // Single word }; } else if (argument instanceof ArgumentString) { argumentNode.parser = "brigadier:string"; argumentNode.properties = packetWriter -> { packetWriter.writeVarInt(1); // Quotable phrase }; } else if (argument instanceof ArgumentStringArray) { argumentNode.parser = "brigadier:string"; argumentNode.properties = packetWriter -> { packetWriter.writeVarInt(2); // Greedy phrase }; } return argumentNode; } }