diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandNode.java b/SpigotCore_Main/src/de/steamwar/command/CommandNode.java index 36b98c5..4778bbc 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandNode.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandNode.java @@ -21,21 +21,30 @@ package de.steamwar.command; import org.bukkit.command.CommandSender; +import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; class CommandNode { + private final SWCommand swCommand; private final TypeMapper typeMapper; private boolean varArg = false; private List commandNodeList = new ArrayList<>(); private Method executor; - CommandNode(TypeMapper typeMapper) { + private Predicate commandSenderPredicate; + private Function commandSenderObjectFunction; + + CommandNode(SWCommand swCommand, TypeMapper typeMapper) { + this.swCommand = swCommand; this.typeMapper = typeMapper; } @@ -44,8 +53,13 @@ class CommandNode { this.varArg = false; } - public void setExecutor(Method method) { + public void setExecutor(Method executor) { + if (this.executor != null) return; this.executor = executor; + + Parameter parameter = executor.getParameters()[0]; + commandSenderPredicate = parameter.getType()::isInstance; + commandSenderObjectFunction = parameter.getType()::cast; } public void setVarArg(boolean varArg) { @@ -77,17 +91,48 @@ class CommandNode { } } - 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]); + public boolean execute(CommandSender commandSender, int index, String[] args, List mappedObjects) { + try { + Object o; + if (varArg) { + o = Array.newInstance(Object.class, args.length - index); + for (int i = 0; i < Array.getLength(o); i++) { + Object current = typeMapper.map(commandSender, Arrays.copyOf(args, index + i), args[index + i]); + if (current == null) return false; + Array.set(o, i, current); + } + } else { + o = typeMapper.map(commandSender, Arrays.copyOf(args, index), args[index]); + if (o == null) return false; } - } else { - + mappedObjects.add(o); + } catch (Exception e) { + return false; } - // if (args.length) - return false; + + if (index == args.length - 1) { + if (executor == null) { + return false; + } + if (!commandSenderPredicate.test(commandSender)) { + return false; + } + + List finalMappedObjects = new ArrayList<>(mappedObjects); + finalMappedObjects.add(0, commandSenderObjectFunction.apply(commandSender)); + + Object[] objects = finalMappedObjects.toArray(new Object[0]); + try { + executor.invoke(swCommand, objects); + return true; + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + } + + return commandNodeList.stream() + .map(commandNode -> commandNode.execute(commandSender, index + 1, args, new ArrayList<>(mappedObjects))) + .findFirst().orElse(false); } }