diff --git a/SpigotCore_Main/pom.xml b/SpigotCore_Main/pom.xml
index 81c3416..9405988 100644
--- a/SpigotCore_Main/pom.xml
+++ b/SpigotCore_Main/pom.xml
@@ -55,14 +55,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- 9
-
-
spigotcore
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java
index e9f9914..fba9c11 100644
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java
@@ -60,6 +60,11 @@ public abstract class SWCommand {
swCommandInterface.register();
}
+ interface SWCommandInterface {
+ void unregister();
+ void register();
+ }
+
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Register.Registeres.class)
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java
index 16ba87b..9e31c8b 100644
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandBrigadier.java
@@ -24,90 +24,36 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.function.BiConsumer;
-import java.util.function.Function;
import java.util.function.IntPredicate;
-import java.util.function.Predicate;
import java.util.logging.Level;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
-import static de.steamwar.command.SWCommandUtils.*;
+class SWCommandBrigadier implements SWCommand.SWCommandInterface {
-class SWCommandBrigadier implements SWCommandInterface {
-
- private SWCommandNormal swCommandNormal = null;
private final SWCommand swCommand;
+ private Command command;
private final List commandList = new ArrayList<>();
private final List commandHelpList = new ArrayList<>();
private final Map> localTypeMapper = new HashMap<>();
protected SWCommandBrigadier(SWCommand swCommand, String command, String... aliases) {
this.swCommand = swCommand;
-
- Method[] methods = swCommand.getClass().getDeclaredMethods();
- for (Method method : methods) {
- addMapper(SWCommand.Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
- (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value(), typeMapper);
- });
- addMapper(SWCommand.ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
- (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value().getTypeName(), typeMapper);
- });
- add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
- if (!anno.help()) return;
- if (parameters.length != 2) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many");
- }
- if (!parameters[parameters.length - 1].isVarArgs()) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument");
- }
- if (parameters[parameters.length - 1].getType().getComponentType() != String.class) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument");
- return;
- }
- commandList.add(createSubCommand(method, anno.value()));
- });
- }
- for (Method method : methods) {
- add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
- if (anno.help()) return;
- for (int i = 1; i < parameters.length; i++) {
- Parameter parameter = parameters[i];
- Class> clazz = parameter.getType();
- if (parameter.isVarArgs() && i == parameters.length - 1) {
- clazz = parameter.getType().getComponentType();
- }
- SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class);
- if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) {
- continue;
- }
- String name = mapper != null ? mapper.value() : clazz.getTypeName();
- if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name) && !localTypeMapper.containsKey(name)) {
- Bukkit.getLogger().log(Level.WARNING, "The parameter '" + parameter + "' is using an unsupported Mapper of type '" + name + "'");
- return;
- }
- }
- commandList.add(createSubCommand(method, anno.value()));
- });
- }
-
- for (SubCommand subCommand : commandList) {
+ SWCommandUtils.createList(swCommand, commandList, commandHelpList, localTypeMapper, this::createSubCommand);
+ Stream.of(commandList, commandHelpList).flatMap(List::stream).forEach(subCommand -> {
register(command, subCommand, command, aliases);
for (String s : aliases) {
register(s, subCommand, command, aliases);
}
- }
- for (SubCommand subCommand : commandHelpList) {
- register(command, subCommand, command, aliases);
- for (String s : aliases) {
- register(s, subCommand, command, aliases);
- }
- }
+ });
}
private SubCommand createSubCommand(Method method, String[] strings) {
@@ -171,8 +117,27 @@ class SWCommandBrigadier implements SWCommandInterface {
if (subCommand.argumentNode == null) {
return;
}
- if (subCommand.normalTabCompleteNeeded) {
- swCommandNormal = new SWCommandNormal(swCommand, command, aliases);
+ if (subCommand.normalTabCompleteNeeded && command == null) {
+ this.command = new Command(command, "", "/" + command, Arrays.asList(aliases)) {
+ @Override
+ public boolean execute(CommandSender sender, String alias, String[] args) {
+ if (commandList.stream().anyMatch(s -> s.invoke(sender, args))) return false;
+ commandHelpList.stream().anyMatch(s -> s.invoke(sender, args));
+ return false;
+ }
+
+ @Override
+ public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
+ String string = args[args.length - 1].toLowerCase();
+ return commandList.stream()
+ .map(s -> s.tabComplete(sender, args))
+ .filter(Objects::nonNull)
+ .flatMap(Collection::stream)
+ .filter(s -> !s.isEmpty())
+ .filter(s -> s.toLowerCase().startsWith(string))
+ .collect(Collectors.toList());
+ }
+ };
}
literalArgumentBuilder.then(subCommand.argumentNode);
SWCommand.dispatcher.register(literalArgumentBuilder);
@@ -211,14 +176,16 @@ class SWCommandBrigadier implements SWCommandInterface {
@Override
public void unregister() {
- if (swCommandNormal == null) return;
- swCommandNormal.unregister();
+ if (command == null) return;
+ SWCommandUtils.knownCommandMap.remove(command.getName());
+ command.getAliases().forEach(SWCommandUtils.knownCommandMap::remove);
+ command.unregister(SWCommandUtils.commandMap);
}
@Override
public void register() {
- if (swCommandNormal == null) return;
- swCommandNormal.register();
+ if (command == null) return;
+ SWCommandUtils.commandMap.register("steamwar", this.command);
}
private ArgumentType> getArgumentType(Parameter parameter, Class> parameterType, SubCommand subCommand) {
@@ -227,32 +194,20 @@ class SWCommandBrigadier implements SWCommandInterface {
argumentType = BoolArgumentType.bool();
} else if (parameterType == int.class || parameterType == Integer.class) {
SWCommand.IntRange intRange = parameter.getAnnotation(SWCommand.IntRange.class);
- if (intRange != null) {
- argumentType = IntegerArgumentType.integer(intRange.min(), intRange.max());
- } else {
- argumentType = IntegerArgumentType.integer();
- }
+ if (intRange != null) argumentType = IntegerArgumentType.integer(intRange.min(), intRange.max());
+ else argumentType = IntegerArgumentType.integer();
} else if (parameterType == float.class || parameterType == Float.class) {
SWCommand.FloatRange floatRange = parameter.getAnnotation(SWCommand.FloatRange.class);
- if (floatRange != null) {
- argumentType = FloatArgumentType.floatArg(floatRange.min(), floatRange.max());
- } else {
- argumentType = FloatArgumentType.floatArg();
- }
+ if (floatRange != null) argumentType = FloatArgumentType.floatArg(floatRange.min(), floatRange.max());
+ else argumentType = FloatArgumentType.floatArg();
} else if (parameterType == long.class || parameterType == Long.class) {
SWCommand.LongRange longRange = parameter.getAnnotation(SWCommand.LongRange.class);
- if (longRange != null) {
- argumentType = LongArgumentType.longArg(longRange.min(), longRange.max());
- } else {
- argumentType = LongArgumentType.longArg();
- }
+ if (longRange != null) argumentType = LongArgumentType.longArg(longRange.min(), longRange.max());
+ else argumentType = LongArgumentType.longArg();
} else if (parameterType == double.class || parameterType == Double.class) {
SWCommand.DoubleRange doubleRange = parameter.getAnnotation(SWCommand.DoubleRange.class);
- if (doubleRange != null) {
- argumentType = DoubleArgumentType.doubleArg(doubleRange.min(), doubleRange.max());
- } else {
- argumentType = DoubleArgumentType.doubleArg();
- }
+ if (doubleRange != null) argumentType = DoubleArgumentType.doubleArg(doubleRange.min(), doubleRange.max());
+ else argumentType = DoubleArgumentType.doubleArg();
} else {
argumentType = StringArgumentType.string();
subCommand.normalTabCompleteNeeded = true;
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandInterface.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandInterface.java
deleted file mode 100644
index 4ba0844..0000000
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommandInterface.java
+++ /dev/null
@@ -1,25 +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;
-
-public interface SWCommandInterface {
- void unregister();
- void register();
-}
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandNormal.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandNormal.java
index b325a81..4017ec5 100644
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommandNormal.java
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandNormal.java
@@ -32,7 +32,7 @@ import java.util.function.IntPredicate;
import java.util.logging.Level;
import java.util.stream.Collectors;
-class SWCommandNormal implements SWCommandInterface {
+class SWCommandNormal implements SWCommand.SWCommandInterface {
private final SWCommand swCommand;
private final Command command;
@@ -65,100 +65,13 @@ class SWCommandNormal implements SWCommandInterface {
};
unregister();
register();
-
- Method[] methods = swCommand.getClass().getDeclaredMethods();
- for (Method method : methods) {
- addMapper(SWCommand.Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
- (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value(), typeMapper);
- });
- addMapper(SWCommand.ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
- (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value().getTypeName(), typeMapper);
- });
- add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
- if (!anno.help()) return;
- if (parameters.length != 2) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many");
- }
- if (!parameters[parameters.length - 1].isVarArgs()) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument");
- }
- if (parameters[parameters.length - 1].getType().getComponentType() != String.class) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument");
- return;
- }
- commandHelpList.add(createSubCommand(method, anno.value()));
- });
- }
- for (Method method : methods) {
- add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
- if (anno.help()) return;
- for (int i = 1; i < parameters.length; i++) {
- Parameter parameter = parameters[i];
- Class> clazz = parameter.getType();
- if (parameter.isVarArgs() && i == parameters.length - 1) {
- clazz = parameter.getType().getComponentType();
- }
- SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class);
- if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) {
- continue;
- }
- String name = mapper != null ? mapper.value() : clazz.getTypeName();
- if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name) && !localTypeMapper.containsKey(name)) {
- Bukkit.getLogger().log(Level.WARNING, "The parameter '" + parameter + "' is using an unsupported Mapper of type '" + name + "'");
- return;
- }
- }
- commandList.add(createSubCommand(method, anno.value()));
- });
-
- this.commandList.sort((o1, o2) -> {
- int compare = Integer.compare(-o1.subCommand.length, -o2.subCommand.length);
- if (compare != 0) {
- return compare;
- } else {
- return Integer.compare(o1.varArgType != null ? Integer.MAX_VALUE : o1.arguments.length,
- o2.varArgType != null ? Integer.MAX_VALUE : o2.arguments.length);
- }
- });
- commandHelpList.sort(Comparator.comparingInt(o -> -o.subCommand.length));
- }
+ SWCommandUtils.createList(swCommand, commandList, commandHelpList, localTypeMapper, this::createSubCommand);
}
- private de.steamwar.command.SubCommand createSubCommand(Method method, String[] strings) {
+ private SubCommand createSubCommand(Method method, String[] strings) {
return new de.steamwar.command.SubCommand(swCommand, method, strings, localTypeMapper, current -> {});
}
- private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer consumer) {
- T[] anno = SWCommandUtils.getAnnotation(method, annotation);
- if (anno == null || anno.length == 0) return;
-
- Parameter[] parameters = method.getParameters();
- if (!parameterTester.test(parameters.length)) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking parameters or has too many");
- return;
- }
- if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking the first parameter of type '" + CommandSender.class.getTypeName() + "'");
- return;
- }
- if (returnType != null && method.getReturnType() != returnType) {
- Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking the desired return type '" + returnType.getTypeName() + "'");
- return;
- }
- Arrays.stream(anno).forEach(t -> consumer.accept(t, parameters));
- }
-
- private void addMapper(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer> consumer) {
- add(annotation, method, parameterTester, firstParameter, returnType, (anno, parameters) -> {
- try {
- method.setAccessible(true);
- consumer.accept(anno, (TypeMapper>) method.invoke(swCommand));
- } catch (Exception e) {
- throw new SecurityException(e.getMessage(), e);
- }
- });
- }
-
public void unregister() {
SWCommandUtils.knownCommandMap.remove(command.getName());
command.getAliases().forEach(SWCommandUtils.knownCommandMap::remove);
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
index e6e0ee4..5b932b3 100644
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
@@ -31,9 +31,13 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
import java.util.*;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
+import java.util.function.IntPredicate;
+import java.util.logging.Level;
import java.util.stream.Collectors;
public class SWCommandUtils {
@@ -178,4 +182,83 @@ public class SWCommandUtils {
if (method.getAnnotations().length != 1) return null;
return method.getDeclaredAnnotationsByType(annotation);
}
+
+ static void createList(SWCommand swCommand, List commandList, List commandHelpList, Map> localTypeMapper, BiFunction creator) {
+ Method[] methods = swCommand.getClass().getDeclaredMethods();
+ for (Method method : methods) {
+ addMapper(swCommand, SWCommand.Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
+ (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value(), typeMapper);
+ });
+ addMapper(swCommand, SWCommand.ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> {
+ (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value().getTypeName(), typeMapper);
+ });
+ add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
+ if (!anno.help()) return;
+ if (parameters.length != 2) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many");
+ }
+ if (!parameters[parameters.length - 1].isVarArgs()) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument");
+ }
+ if (parameters[parameters.length - 1].getType().getComponentType() != String.class) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument");
+ return;
+ }
+ commandHelpList.add(creator.apply(method, anno.value()));
+ });
+ }
+ for (Method method : methods) {
+ add(SWCommand.Register.class, method, i -> i > 0, true, null, (anno, parameters) -> {
+ if (anno.help()) return;
+ for (int i = 1; i < parameters.length; i++) {
+ Parameter parameter = parameters[i];
+ Class> clazz = parameter.getType();
+ if (parameter.isVarArgs() && i == parameters.length - 1) {
+ clazz = parameter.getType().getComponentType();
+ }
+ SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class);
+ if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) {
+ continue;
+ }
+ String name = mapper != null ? mapper.value() : clazz.getTypeName();
+ if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name) && !localTypeMapper.containsKey(name)) {
+ Bukkit.getLogger().log(Level.WARNING, "The parameter '" + parameter + "' is using an unsupported Mapper of type '" + name + "'");
+ return;
+ }
+ }
+ commandList.add(creator.apply(method, anno.value()));
+ });
+ }
+ }
+
+ private static void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer consumer) {
+ T[] anno = SWCommandUtils.getAnnotation(method, annotation);
+ if (anno == null || anno.length == 0) return;
+
+ Parameter[] parameters = method.getParameters();
+ if (!parameterTester.test(parameters.length)) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking parameters or has too many");
+ return;
+ }
+ if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking the first parameter of type '" + CommandSender.class.getTypeName() + "'");
+ return;
+ }
+ if (returnType != null && method.getReturnType() != returnType) {
+ Bukkit.getLogger().log(Level.WARNING, "The method '" + method + "' is lacking the desired return type '" + returnType.getTypeName() + "'");
+ return;
+ }
+ Arrays.stream(anno).forEach(t -> consumer.accept(t, parameters));
+ }
+
+ private static void addMapper(SWCommand swCommand, Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class> returnType, BiConsumer> consumer) {
+ add(annotation, method, parameterTester, firstParameter, returnType, (anno, parameters) -> {
+ try {
+ method.setAccessible(true);
+ consumer.accept(anno, (TypeMapper>) method.invoke(swCommand));
+ } catch (Exception e) {
+ throw new SecurityException(e.getMessage(), e);
+ }
+ });
+ }
}