From 23826a084240ace008045f658bf63c0db995f649 Mon Sep 17 00:00:00 2001 From: Felix Cravic Date: Fri, 10 Jul 2020 18:12:29 +0200 Subject: [PATCH] Reworked command packet --- src/main/java/fr/themode/demo/PlayerInit.java | 7 - .../themode/demo/commands/HealthCommand.java | 2 +- .../server/command/CommandManager.java | 217 ++++++++++++++---- .../builder/arguments/ArgumentWord.java | 8 + .../arguments/number/ArgumentNumber.java | 16 +- 5 files changed, 198 insertions(+), 52 deletions(-) diff --git a/src/main/java/fr/themode/demo/PlayerInit.java b/src/main/java/fr/themode/demo/PlayerInit.java index a9a8e1f87..a8ecfe1d7 100644 --- a/src/main/java/fr/themode/demo/PlayerInit.java +++ b/src/main/java/fr/themode/demo/PlayerInit.java @@ -6,9 +6,7 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.benchmark.BenchmarkManager; import net.minestom.server.benchmark.ThreadResult; import net.minestom.server.chat.ChatColor; -import net.minestom.server.chat.ChatHoverEvent; import net.minestom.server.chat.ColoredText; -import net.minestom.server.chat.RichMessage; import net.minestom.server.entity.*; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.fakeplayer.FakePlayer; @@ -286,11 +284,6 @@ public class PlayerInit { //player.sendLegacyMessage("&aIm &bHere", '&'); //player.sendMessage(ColoredText.of("{#ff55ff}" + ChatColor.RESET + "test")); - RichMessage richMessage = RichMessage.of(ColoredText.of("Hey the item")) - .setHoverEvent(ChatHoverEvent.showItem(item)); - System.out.println(richMessage.toString()); - player.sendMessage(richMessage); - }); player.addEventCallback(PlayerRespawnEvent.class, event -> { diff --git a/src/main/java/fr/themode/demo/commands/HealthCommand.java b/src/main/java/fr/themode/demo/commands/HealthCommand.java index 0c8c9b8d3..bf53fb46f 100644 --- a/src/main/java/fr/themode/demo/commands/HealthCommand.java +++ b/src/main/java/fr/themode/demo/commands/HealthCommand.java @@ -24,8 +24,8 @@ public class HealthCommand extends Command { addCallback(this::modeCallback, arg0); addCallback(this::valueCallback, arg1); - //addSyntax(this::execute, arg0); addSyntax(this::execute2, arg0, arg1); + addSyntax(this::execute, arg0); } private boolean condition(CommandSender sender) { diff --git a/src/main/java/net/minestom/server/command/CommandManager.java b/src/main/java/net/minestom/server/command/CommandManager.java index b9aff94d2..0b1ef1f7b 100644 --- a/src/main/java/net/minestom/server/command/CommandManager.java +++ b/src/main/java/net/minestom/server/command/CommandManager.java @@ -7,6 +7,7 @@ import net.minestom.server.command.builder.arguments.*; 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; +import net.minestom.server.command.builder.condition.CommandCondition; import net.minestom.server.entity.Player; import net.minestom.server.event.player.PlayerCommandEvent; import net.minestom.server.network.packet.server.play.DeclareCommandsPacket; @@ -102,7 +103,7 @@ public class CommandManager { } public DeclareCommandsPacket createDeclareCommandsPacket(Player player) { - return buildPacket2(player); + return buildPacket(player); } /*private DeclareCommandsPacket buildPacket(Player player) { @@ -176,45 +177,65 @@ public class CommandManager { return declareCommandsPacket; }*/ - private DeclareCommandsPacket buildPacket2(Player player) { + private DeclareCommandsPacket buildPacket(Player player) { DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket(); List nodes = new ArrayList<>(); + // Contains the children of the main node (all commands name) ArrayList rootChildren = new ArrayList<>(); for (Command command : dispatcher.getCommands()) { + // Check if player should see this command + CommandCondition commandCondition = command.getCondition(); + if (commandCondition != null) { + // Do not show command if return false + if (!commandCondition.apply(player)) { + continue; + } + } + + // The main root of this command ArrayList cmdChildren = new ArrayList<>(); + Collection syntaxes = command.getSyntaxes(); - String name = command.getName(); + List 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); + } + } + + final List simpleCommands = new ArrayList<>(); + for (CommandProcessor commandProcessor : commandProcessorMap.values()) { + // Do not show command if return false + if (!commandProcessor.hasAccess(player)) + continue; + + 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 DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node(); - literalNode.flags = 0b1; // literal - literalNode.name = name; + literalNode.flags = getFlag(NodeType.LITERAL, true, false, false); + literalNode.name = simpleCommand; + literalNode.children = new int[0]; + //literalNode.suggestionsType = "minecraft:ask_server"; 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); @@ -227,55 +248,171 @@ public class CommandManager { return declareCommandsPacket; } - private DeclareCommandsPacket.Node toNode(Argument argument) { - DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node(); - argumentNode.flags = getFlag(NodeType.ARGUMENT, true, false, false); - argumentNode.name = argument.getId(); + private void createCommand(List nodes, ArrayList cmdChildren, String name, Collection syntaxes, ArrayList 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 lastNodes = null; + + // Represent the children of the last node + ArrayList 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 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) { + int[] children = ArrayUtils.toArray(argChildren); + 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 + int[] children = new int[0]; + argumentNodes.forEach(node -> node.children = children); + } else { + // Create children list which will be filled during next iteration + argChildren = new ArrayList<>(); + lastNodes = argumentNodes; + } + } + + } + int[] children = ArrayUtils.toArray(cmdChildren); + //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; + } + + private List toNodes(Argument argument, boolean executable) { + List nodes = new ArrayList<>(); if (argument instanceof ArgumentBoolean) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + argumentNode.parser = "brigadier:bool"; argumentNode.properties = packetWriter -> packetWriter.writeByte((byte) 0); } else if (argument instanceof ArgumentDouble) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + ArgumentDouble argumentDouble = (ArgumentDouble) argument; argumentNode.parser = "brigadier:double"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); - packetWriter.writeDouble(argumentDouble.min); - packetWriter.writeDouble(argumentDouble.max); + packetWriter.writeDouble(argumentDouble.getMin()); + packetWriter.writeDouble(argumentDouble.getMax()); }; } else if (argument instanceof ArgumentFloat) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + ArgumentFloat argumentFloat = (ArgumentFloat) argument; argumentNode.parser = "brigadier:float"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); - packetWriter.writeFloat(argumentFloat.min); - packetWriter.writeFloat(argumentFloat.max); + packetWriter.writeFloat(argumentFloat.getMin()); + packetWriter.writeFloat(argumentFloat.getMax()); }; } else if (argument instanceof ArgumentInteger) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + ArgumentInteger argumentInteger = (ArgumentInteger) argument; argumentNode.parser = "brigadier:integer"; argumentNode.properties = packetWriter -> { packetWriter.writeByte((byte) 0b11); - packetWriter.writeInt(argumentInteger.min); - packetWriter.writeInt(argumentInteger.max); + packetWriter.writeInt(argumentInteger.getMin()); + packetWriter.writeInt(argumentInteger.getMax()); }; } else if (argument instanceof ArgumentWord) { - argumentNode.parser = "brigadier:string"; - argumentNode.properties = packetWriter -> { - packetWriter.writeVarInt(0); // Single word - }; + + ArgumentWord argumentWord = (ArgumentWord) argument; + + final boolean hasRestriction = argumentWord.hasRestrictions(); + if (hasRestriction) { + 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; + + argumentNode.parser = "brigadier:string"; + argumentNode.properties = packetWriter -> { + packetWriter.writeVarInt(0); // Single word + }; + } + } else { + + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + + argumentNode.parser = "brigadier:string"; + argumentNode.properties = packetWriter -> { + packetWriter.writeVarInt(0); // Single word + }; + } } else if (argument instanceof ArgumentString) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + argumentNode.parser = "brigadier:string"; argumentNode.properties = packetWriter -> { packetWriter.writeVarInt(1); // Quotable phrase }; } else if (argument instanceof ArgumentStringArray) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable); + argumentNode.parser = "brigadier:string"; argumentNode.properties = packetWriter -> { packetWriter.writeVarInt(2); // Greedy phrase }; } + return nodes; + } + + private DeclareCommandsPacket.Node simpleArgumentNode(List nodes, + Argument argument, boolean executable) { + DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node(); + nodes.add(argumentNode); + + argumentNode.flags = getFlag(NodeType.ARGUMENT, executable, false, false); + argumentNode.name = argument.getId(); + return argumentNode; } @@ -291,7 +428,7 @@ public class CommandManager { } if (suggestionType) { - result |= 0x1; + result |= 0x10; } return result; } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java index 9ee8ffe87..39a26b0b7 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java @@ -45,4 +45,12 @@ public class ArgumentWord extends Argument { return SUCCESS; } + + public boolean hasRestrictions() { + return restrictions != null && restrictions.length > 0; + } + + public String[] getRestrictions() { + return restrictions; + } } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/number/ArgumentNumber.java b/src/main/java/net/minestom/server/command/builder/arguments/number/ArgumentNumber.java index 5fac60417..fdf9f43ef 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/number/ArgumentNumber.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/number/ArgumentNumber.java @@ -10,7 +10,7 @@ public abstract class ArgumentNumber extends Argument { public static final int NOT_NUMBER_ERROR = 1; public static final int RANGE_ERROR = 2; - public T min, max; + protected T min, max; public ArgumentNumber(String id) { super(id, false); @@ -32,7 +32,15 @@ public abstract class ArgumentNumber extends Argument { return this; } - public String parseValue(String value) { + public T getMin() { + return min; + } + + public T getMax() { + return max; + } + + protected String parseValue(String value) { if (value.startsWith("0b")) { value = value.replaceFirst(Pattern.quote("0b"), ""); } else if (value.startsWith("0x")) { @@ -44,7 +52,7 @@ public abstract class ArgumentNumber extends Argument { return value; } - public int getRadix(String value) { + protected int getRadix(String value) { if (value.startsWith("0b")) { return 2; } else if (value.startsWith("0x")) { @@ -53,7 +61,7 @@ public abstract class ArgumentNumber extends Argument { return 10; } - public String removeScientificNotation(String value) { + protected String removeScientificNotation(String value) { try { return new BigDecimal(value).toPlainString(); } catch (NumberFormatException e) {