diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandNode.java b/SpigotCore_Main/src/de/steamwar/command/CommandNode.java new file mode 100644 index 0000000..36b98c5 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/CommandNode.java @@ -0,0 +1,93 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.command; + +import org.bukkit.command.CommandSender; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +class CommandNode { + + private final TypeMapper typeMapper; + private boolean varArg = false; + private List commandNodeList = new ArrayList<>(); + private Method executor; + + CommandNode(TypeMapper typeMapper) { + this.typeMapper = typeMapper; + } + + public void addNode(CommandNode commandNode) { + commandNodeList.add(commandNode); + this.varArg = false; + } + + public void setExecutor(Method method) { + this.executor = executor; + } + + public void setVarArg(boolean varArg) { + if (commandNodeList.isEmpty()) { + this.varArg = varArg; + } else { + this.varArg = false; + } + } + + public List tabComplete(CommandSender commandSender, int index, String[] args) { + try { + if (index == args.length - 1) { + return typeMapper.tabCompletes(commandSender, Arrays.copyOf(args, index), args[args.length - 1]); + } + if (typeMapper.map(commandSender, Arrays.copyOf(args, index), args[index]) == null) { + return Collections.emptyList(); + } + if (varArg) { + return tabComplete(commandSender, index + 1, args); + } else { + return commandNodeList.stream() + .map(commandNode -> commandNode.tabComplete(commandSender, index + 1, args)) + .flatMap(List::stream) + .collect(Collectors.toList()); + } + } catch (Exception e) { + return Collections.emptyList(); + } + } + + public boolean execute(CommandSender commandSender, int index, String[] args) { + if (varArg) { + for (int i = index; i < args.length; i++) { + String[] previousArgs = Arrays.copyOf(args, i); + typeMapper.map(commandSender, previousArgs, args[i]); + } + } else { + + } + // if (args.length) + return false; + } + +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java index 3c4e879..4f7d386 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java @@ -23,6 +23,7 @@ import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.tree.CommandNode; import net.minecraft.server.v1_15_R1.CommandListenerWrapper; import org.bukkit.command.CommandSender; @@ -60,51 +61,88 @@ class SWCommandBrigadier implements SWCommand.SWCommandInterface { private SubCommand createSubCommand(Method method, String[] strings) { return new SubCommand(swCommand, method, strings, localTypeMapper, current -> { - ArgumentBuilder argumentBuilder = null; + List argumentBuilders = new ArrayList<>(); + for (String s : current.subCommand) { LiteralArgumentBuilder literalArgumentBuilder = LiteralArgumentBuilder.literal(s); - if (argumentBuilder != null) { - argumentBuilder.then(literalArgumentBuilder); - } else { - current.argumentNode = literalArgumentBuilder; + List currentBuilders = new ArrayList<>(); + argumentBuilders.forEach(currrentBuilder -> { + currentBuilders.add(currrentBuilder.then(literalArgumentBuilder)); + }); + if (argumentBuilders.isEmpty()) { + currentBuilders.add(literalArgumentBuilder); + if (current.argumentNode.isEmpty()) { + current.argumentNode.add(literalArgumentBuilder); + } } - argumentBuilder = literalArgumentBuilder; + argumentBuilders = currentBuilders; } for (int i = 0; i < current.arguments.length - (current.varArgType != null ? 1 : 0); i++) { Parameter parameter = current.parameters[i + 1]; Class parameterType = parameter.getType(); - ArgumentType argumentType = getArgumentType(parameter, parameterType, current); - RequiredArgumentBuilder requiredArgumentBuilder = RequiredArgumentBuilder.argument(parameter.getName(), argumentType); - if (argumentBuilder != null) { - argumentBuilder.then(requiredArgumentBuilder); + ArgumentType argumentType = getArgumentType(parameter, parameterType); + List newBuilders = new ArrayList<>(); + if (argumentType == null) { + try { + current.arguments[i].tabCompletes(null, null, "").stream() + .map(LiteralArgumentBuilder::literal) + .forEach(newBuilders::add); + } catch (Exception e) { + newBuilders.add(RequiredArgumentBuilder.argument(parameter.getName(), StringArgumentType.string())); + } } else { - current.argumentNode = requiredArgumentBuilder; + newBuilders.add(RequiredArgumentBuilder.argument(parameter.getName(), argumentType)); } - argumentBuilder = requiredArgumentBuilder; + + List currentBuilders = new ArrayList<>(); + argumentBuilders.forEach(currrentBuilder -> { + newBuilders.forEach(argumentBuilder -> { + currentBuilders.add(currrentBuilder.then(argumentBuilder)); + }); + }); + if (argumentBuilders.isEmpty()) { + currentBuilders.addAll(newBuilders); + if (current.argumentNode.isEmpty()) { + current.argumentNode.addAll(newBuilders); + } + } + argumentBuilders = currentBuilders; } if (current.varArgType != null) { - // TODO: UNSUPPORTED - /*Parameter parameter = parameters[parameters.length - 1]; + Parameter parameter = current.parameters[current.parameters.length - 1]; Class parameterType = parameter.getType(); - TypeMapper typeMapper = arguments[arguments.length - 1]; - ArgumentType argumentType = getArgumentType(parameter, parameterType, typeMapper); - - RequiredArgumentBuilder requiredArgumentBuilder = RequiredArgumentBuilder.argument(parameter.getName(), argumentType); - if (argumentBuilder != null) { - argumentBuilder.then(requiredArgumentBuilder); + ArgumentType argumentType = getArgumentType(parameter, parameterType); + List newBuilders = new ArrayList<>(); + if (argumentType == null) { + try { + current.arguments[current.arguments.length - 1].tabCompletes(null, null, "").stream() + .map(LiteralArgumentBuilder::literal) + .forEach(newBuilders::add); + } catch (Exception e) { + newBuilders.add(RequiredArgumentBuilder.argument(parameter.getName(), StringArgumentType.string())); + } } else { - argumentNode = requiredArgumentBuilder; + newBuilders.add(RequiredArgumentBuilder.argument(parameter.getName(), argumentType)); } - argumentBuilder = requiredArgumentBuilder; - argumentBuilder.executes(commandContext -> { - invoke((CommandSender) commandContext.getCommand(), commandContext.getInput().split(" ")); - return 0; + + // TODO: VarArgs + List currentBuilders = new ArrayList<>(); + argumentBuilders.forEach(currrentBuilder -> { + newBuilders.forEach(argumentBuilder -> { + currentBuilders.add(currrentBuilder.then(argumentBuilder)); + }); }); - CommandNode commandNode = argumentBuilder.build(); - argumentBuilder.redirect(commandNode);*/ + if (argumentBuilders.isEmpty()) { + currentBuilders.addAll(newBuilders); + if (current.argumentNode.isEmpty()) { + current.argumentNode.addAll(newBuilders); + } + } + currentBuilders.forEach(argumentBuilder -> argumentBuilder.executes(executes(current))); + argumentBuilders = currentBuilders; } - current.argumentNodeEnd = argumentBuilder; + current.argumentNodeEnd.addAll(argumentBuilders); }); } @@ -126,8 +164,8 @@ class SWCommandBrigadier implements SWCommand.SWCommandInterface { SWCommand.dispatcher.register(literalArgumentBuilder); return; } - subCommand.argumentNodeEnd.executes(executes(subCommand)); - literalArgumentBuilder.then(subCommand.argumentNode); + subCommand.argumentNodeEnd.forEach(argumentBuilder -> argumentBuilder.executes(executes(subCommand))); + subCommand.argumentNode.forEach(literalArgumentBuilder::then); SWCommand.dispatcher.register(literalArgumentBuilder); } @@ -147,7 +185,7 @@ class SWCommandBrigadier implements SWCommand.SWCommandInterface { }); } - private ArgumentType getArgumentType(Parameter parameter, Class parameterType, SubCommand subCommand) { + private ArgumentType getArgumentType(Parameter parameter, Class parameterType) { ArgumentType argumentType; if (parameterType == boolean.class || parameterType == Boolean.class) { argumentType = BoolArgumentType.bool(); @@ -168,7 +206,7 @@ class SWCommandBrigadier implements SWCommand.SWCommandInterface { if (doubleRange != null) argumentType = DoubleArgumentType.doubleArg(doubleRange.min(), doubleRange.max()); else argumentType = DoubleArgumentType.doubleArg(); } else { - argumentType = StringArgumentType.string(); + return null; } return argumentType; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 4119686..6dffc9b 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -34,8 +34,8 @@ import static de.steamwar.command.SWCommandUtils.*; class SubCommand { - ArgumentBuilder argumentNode = null; - ArgumentBuilder argumentNodeEnd = null; + List argumentNode = new ArrayList<>(); + List argumentNodeEnd = new ArrayList<>(); SWCommand swCommand; Parameter[] parameters;