diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java deleted file mode 100644 index 6481fa3..0000000 --- a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.Collections; -import java.util.List; - -class InternalCommand { - - private SWCommand swCommand; - private Method method; - private int increment = 0; - private Parameter[] parameters; - - InternalCommand(SWCommand swCommand, Method method) { - this.swCommand = swCommand; - this.method = method; - parameters = method.getParameters(); - - increment = method.getAnnotation(SWCommand.Register.class).subCommand().length; - } - - boolean invoke(CommandSender commandSender, String[] args) { - if (args.length < parameters.length - 1) { - return false; - } - try { - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); - method.setAccessible(true); - method.invoke(swCommand, objects); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException e) { - return false; - } - return true; - } - - List tabComplete(String[] args) { - if (args.length > parameters.length - increment) { - if (parameters[parameters.length - 1].isVarArgs()) { - String name = parameters[parameters.length - 1].getType().getComponentType().getTypeName(); - SWCommand.Mapper mapper = parameters[parameters.length - 1].getAnnotation(SWCommand.Mapper.class); - if (mapper != null) { - name = mapper.mapper(); - } - try { - return SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); - } catch (Exception e) { - // Ignored - } - } - return Collections.emptyList(); - } - String name = parameters[args.length - increment + 1].getType().getTypeName(); - SWCommand.Mapper mapper = parameters[args.length - increment + 1].getAnnotation(SWCommand.Mapper.class); - if (mapper != null) { - name = mapper.mapper(); - } - try { - return SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); - } catch (Exception e) { - return Collections.emptyList(); - } - } - -} diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java deleted file mode 100644 index cb7c655..0000000 --- a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; - -class InternalTabComplete { - - private SWCommand swCommand; - private Method method; - private Parameter[] parameters; - - InternalTabComplete(SWCommand swCommand, Method method) { - this.swCommand = swCommand; - this.method = method; - parameters = method.getParameters(); - } - - SWCommandUtils.TabComplete invoke(CommandSender commandSender, String[] args) { - if (args.length < parameters.length - 1) { - return null; - } - try { - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); - method.setAccessible(true); - return (SWCommandUtils.TabComplete) method.invoke(swCommand, objects); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException e) { - return null; - } - } - -} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 81e7fed..e5923e0 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -33,9 +33,7 @@ import java.util.function.Consumer; public abstract class SWCommand { - private final Set commandSet = new HashSet<>(); - private final Set tabCompleteSet = new HashSet<>(); - private final Map> subCommandTabCompletes = new HashMap<>(); + private final Set commandSet = new HashSet<>(); private Consumer helpMessage = sender -> { }; @@ -47,8 +45,8 @@ public abstract class SWCommand { SWCommandUtils.commandMap.register("steamwar", new Command(command, "", "/" + command, Arrays.asList(aliases)) { @Override public boolean execute(CommandSender sender, String alias, String[] args) { - for (InternalCommand internalCommand : commandSet) { - if (internalCommand.invoke(sender, args)) { + for (SubCommand subCommand : commandSet) { + if (subCommand.invoke(sender, args)) { return false; } } @@ -58,17 +56,11 @@ public abstract class SWCommand { @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { - List strings = new ArrayList<>(subCommandTabCompletes.getOrDefault(args.length, new HashSet<>())); - for (InternalTabComplete internalTabComplete : tabCompleteSet) { - SWCommandUtils.TabComplete tabComplete = internalTabComplete.invoke(sender, args); - if (tabComplete != null) { - strings.addAll(tabComplete.tabCompletes); - } - } - for (InternalCommand internalCommand : commandSet) { - List stringList = internalCommand.tabComplete(args); - if (stringList != null) { - strings.addAll(stringList); + List strings = new ArrayList<>(); + for (SubCommand subCommand : commandSet) { + List tabCompletes = subCommand.tabComplete(sender, args); + if (tabCompletes != null) { + strings.addAll(tabCompletes); } } strings = new ArrayList<>(strings); @@ -86,19 +78,10 @@ public abstract class SWCommand { if (register == null) { continue; } - for (int i = 0; i < register.subCommand().length; i++) { - subCommandTabCompletes.computeIfAbsent(i, integer -> new HashSet<>()).add(register.subCommand()[i]); - } - if (!validMethod(method)) { continue; } - if (method.getReturnType() == Void.TYPE) { - commandSet.add(new InternalCommand(this, method)); - } - if (method.getReturnType() == SWCommandUtils.TabComplete.class) { - tabCompleteSet.add(new InternalTabComplete(this, method)); - } + commandSet.add(new SubCommand(this, method)); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 4df770d..f3ddf9c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -40,7 +40,7 @@ class SWCommandUtils { static final Map> MAPPER_FUNCTIONS = new HashMap<>(); - static final TypeMapper ERROR_FUNCTION = new TypeMapper<>() { + static final TypeMapper ERROR_FUNCTION = new TypeMapper() { @Override public Object map(String s) { throw new SecurityException(); @@ -173,36 +173,31 @@ class SWCommandUtils { } } - public static Object[] generateArgumentArray(CommandSender commandSender, Method method, Parameter[] parameters, String[] args) { - Object[] arguments = new Object[args.length + 1]; - boolean varArgs = false; - if (parameters[parameters.length - 1].isVarArgs()) { - varArgs = true; - arguments = new Object[parameters.length]; - } - arguments[0] = parameters[0].getType().cast(commandSender); - - SWCommand.Register register = method.getAnnotation(SWCommand.Register.class); - int subCommandIndex = 1; - for (String s : register.subCommand()) { - if (!args[subCommandIndex++].equals(s)) throw new SecurityException(); + public static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) { + Object[] arguments = new Object[parameters.length + 1]; + int index = 0; + while (index < subCommand.length) { + if (!args[index].equals(subCommand[index])) { + throw new SecurityException(); + } + index++; } - for (int i = subCommandIndex; i < parameters.length - (varArgs ? 1 : 0); i++) { - arguments[i] = mapper(parameters[i]).apply(args[i - 1]); + for (int i = 0; i < parameters.length - (varArgs ? 1 : 0); i++) { + arguments[i + 1] = parameters[i].map(args[index++]); + if (arguments[i + 1] == null) { + throw new SecurityException(); + } } if (varArgs) { Object[] varArgument = new Object[args.length - parameters.length + 2]; arguments[arguments.length - 1] = varArgument; - Function mapper = mapper(parameters[parameters.length - 1]); - int index = 0; - for (int i = parameters.length - 2; i < args.length; i++) { - varArgument[index++] = mapper.apply(args[i]); + for (int i = 0; i < varArgument.length; i++) { + varArgument[i] = parameters[parameters.length - 1].map(args[index++]); } } - return arguments; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java new file mode 100644 index 0000000..96a21ec --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -0,0 +1,92 @@ +package de.steamwar.command; + +import org.bukkit.command.CommandSender; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +class SubCommand { + + private SWCommand swCommand; + private Method method; + private String[] subCommand; + private TypeMapper[] arguments; + private boolean varArgs = false; + private Function commandSenderFunction; + + public SubCommand(SWCommand swCommand, Method method) { + this.swCommand = swCommand; + this.method = method; + + Parameter[] parameters = method.getParameters(); + commandSenderFunction = sender -> parameters[0].getType().cast(sender); + SWCommand.Register register = method.getAnnotation(SWCommand.Register.class); + subCommand = register.subCommand(); + + arguments = new TypeMapper[parameters.length - 1]; + for (int i = 1; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + Class clazz = parameter.getType(); + if (parameter.isVarArgs()) { + varArgs = true; + clazz = clazz.getComponentType(); + } + + if (clazz.isEnum()) { + Class> enumClass = (Class>) clazz; + List tabCompletes = new ArrayList<>(); + for (Enum enumConstant : enumClass.getEnumConstants()) { + tabCompletes.add(enumConstant.name().toLowerCase()); + } + arguments[i] = new TypeMapper() { + @Override + public Object map(String s) { + return SWCommandUtils.ENUM_MAPPER.apply(enumClass, s); + } + + @Override + public List tabCompletes(String s) { + return tabCompletes; + } + }; + continue; + } + + String name = clazz.getTypeName(); + SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); + if (mapper != null) { + name = mapper.mapper(); + } + + arguments[i] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); + } + } + + boolean invoke(CommandSender commandSender, String[] args) { + if (args.length < arguments.length - 1) { + return false; + } + try { + Object[] objects = SWCommandUtils.generateArgumentArray(arguments, args, varArgs, subCommand); + objects[0] = commandSenderFunction.apply(commandSender); + method.setAccessible(true); + method.invoke(swCommand, objects); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new SecurityException(e.getMessage(), e); + } catch (InvocationTargetException e) { + return false; + } + return true; + } + + List tabComplete(CommandSender commandSender, String[] args) { + // TODO: implement tabCompleting for SubCommand + return null; + } + +}